边分治求调
查看原帖
边分治求调
350297
_maojun_楼主2024/1/25 21:10
#include<bits/extc++.h>
#define eb emplace_back
using namespace std;

typedef long long ll;
const int N=2e5+5;
int n,idx,a[N];
const int E=N<<1;
int tot,head[N],to[E],ew[E],nxt[E];
inline void add(int u,int v,int w){to[++tot]=v;ew[tot]=w;nxt[tot]=head[u];head[u]=tot;}
inline void Add(int u,int v,int w){add(u,v,w);add(v,u,w);}
#define go(u,i) for(int i=head[u];i;i=nxt[i])

vector<pair<int,int>>g[N];
void dfs(int u,int fath){go(u,i){int v=to[i];if(v^fath){dfs(v,u);g[u].eb(v,ew[i]);}}}
inline void rebuild(){
	dfs(1,0);idx=n;
	tot=1;memset(head,0,sizeof head);
	for(int u=1;u<=idx;u++)
		if(g[u].size()<3)for(auto[v,w]:g[u])Add(u,v,w);
		else{
			int l=++idx,r=++idx;a[l]=a[r]=a[u];Add(u,l,a[u]);Add(u,r,a[u]);
			for(auto[v,w]:g[u])g[l^=r^=l^=r].eb(v,w);
		}
}

int als,mms,wc,sz[N];bool vis[N];
void gwc(int u,int fath){
	int mx=0;sz[u]=1;
	go(u,i){
		int v=to[i];if(v==fath||vis[i>>1])continue;
		gwc(v,u);sz[u]+=sz[v];
		if(int w=max(sz[v],als-sz[v]);w<mms){mms=w;wc=i;}
	}
}
vector<ll>d1,d2;
void gd1(int u,int fath,ll w,ll d,ll mx){
	if(u<=n&&w-d>=mx)d1.eb(mx=w-d);
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i];if(v==fath||vis[i>>1])continue;
		gd1(v,u,w+a[v],d+ew[i],mx);
	}
}
void gd2(int u,int fath,ll w,ll d,ll mx){
	if(u<=n)d2.eb(mx=max(mx,d-w));
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i];if(v==fath||vis[i>>1])continue;
		gd2(v,u,w+a[u],d+ew[i],mx);
	}
}
ll sum=0;
inline void calc(int e){
	int u=to[e],v=to[e^1];
	d1.clear();gd1(u,v,a[u],ew[e],max(0,a[u]-ew[e]));sort(d1.begin(),d1.end());
	d2.clear();gd2(v,u,0,0,0);sort(d2.begin(),d2.end());
	int l1=d1.size(),l2=d2.size();
	for(int i=0,j=0;i<l1;i++){while(j<l2&&d2[j]<=d1[i])j++;sum+=j;}
}
#define __div(u,s) {als=mms=s;wc=0;gwc(u,0);if(wc)divide(wc);}
void divide(int e){
	int u=to[e],v=to[e^1];vis[e>>1]=true;
	calc(e);calc(e^1);
	__div(v,als-sz[u]);__div(u,sz[u]);
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1,u,v,w;i<n;i++){scanf("%d%d%d",&u,&v,&w);Add(u,v,w);}
	rebuild();__div(1,idx);
	printf("%lld\n",sum);
	return 0;
}

只能过链的点,而且把三度化删掉就能过,应该是对虚点虚边的处理错了,但没看出来。

2024/1/25 21:10
加载中...