BZOJ4860: [Beijing2017]树的难题

题面

对于每个重心,每个子树可以求出一个数组,表示每个深度的答案。先同种颜色合并,再不同颜色合并。合并可以按高度从小到大排序,然后跑单调队列,复杂度$O(n\log n)$。我比较脑抽,写的是从大到小排序,然后跑线段树,复杂度$O(n\log^2 n)$。

#include
#define pb push_back
#define RAN(v)v.begin(),v.end()
#define FOR(i,v)\
	for(typeof(v.end())i=v.begin();i!=v.end();++i)
#define I (J+1)
#define J (i+j>>1)
#define P (k<<1)
#define S (P^1)
using namespace std;
const int inf=2e9;
struct buf{
	operator int(){
		int x=0,y=0,c=getchar();
		while(c<48)
			y=c==45,c=getchar();
		while(c>47)
			x=x*10+c-48,c=getchar();
		return y?-x:x;
	}
}it;
const int N=2e5+5;
struct info{int v,c;};
vectore[N];
int ans=-inf;
int n,m,l,r,siz[N],w[N];
bool vis[N];
int len,f[N*4];
void pre(vector&v,int i,int j,int k){
	if(i==j)f[k]=v[i-1];
	else{
		pre(v,i,J,P),pre(v,I,j,S);
		f[k]=max(f[P],f[S]);
	}
}
void pre(vector&v){
	len=v.size();
	pre(v,1,len,1);
}
void cov(int u,int v,int i,int j,int k){
	if(i==j)f[k]=max(f[k],v);
	else{
		uJ?ask(u,v,I,j,S):max(ask(u,J,i,J,P),ask(I,v,I,j,S));
}
int ask(int u,int v){
	u=max(u,1);
	v=min(v,len);
	return u>v?-inf:ask(u,v,1,len,1);
}
bool cmp(const vector&a,const vector&b){
	return a.size()>b.size();
}
void dfs1(int u,int p){
	siz[u]=1;
	FOR(i,e[u])
		if(i->v!=p&&!vis[i->v])
			dfs1(i->v,u),siz[u]+=siz[i->v];
}
int dfs2(int u,int p,int n){
	int s=n-siz[u];
	FOR(i,e[u])
		if(i->v!=p&&!vis[i->v]){
			if(int c=dfs2(i->v,u,n))return c;
			s=max(s,siz[i->v]);
		}
	return s*2<=n?u:0;
}
int dfs4(int u,int p,int d){
	int s=d;
	if(dv!=p&&!vis[i->v])
				s=max(s,dfs4(i->v,u,d+1));
	return s;
}
vectorcur;
void dfs5(int u,int p,int c,int d,int s){
	cur[d]=max(cur[d],s);
	if(dv!=p&&!vis[i->v])
				dfs5(i->v,u,i->c,d+1,c!=i->c?s+w[i->c]:s);
}
void dfs3(int u){
	dfs1(u,0);
	if(siz[u]>l){
		u=dfs2(u,0,siz[u]);
		vis[u]=1;
		map > >col;
		FOR(i,e[u])
			if(!vis[i->v]){
				int n=dfs4(i->v,0,1);
				cur.assign(n,-inf);
				dfs5(i->v,0,i->c,0,w[i->c]);
				col[i->c].pb(cur);
			}
		vector >tmp;
		FOR(i,col){
			sort(RAN(i->second),cmp);
			vector&s=i->second.front();
			pre(s);
			FOR(j,i->second)
				if(j!=i->second.begin()){
					vector&v=*j;
					if(v.size()+len>=l)
						for(int k=0;kfirst]);
						}
					for(int k=0;k1){
			sort(RAN(tmp),cmp);
			pre(tmp.front());
			FOR(i,tmp)
				if(i!=tmp.begin()){
					vector&v=*i;
					if(v.size()+len>=l)
						for(int j=0;jv])dfs3(i->v);
	}
}
int main(){
	n=it,m=it,l=it,r=it;
	for(int i=1;i<=m;++i)
		w[i]=it;
	for(int i=2;i<=n;++i){
		int u=it,v=it,c=it;
		e[u].pb({v,c});
		e[v].pb({u,c});
	}
	dfs3(1);
	printf("%d\n",ans);
}

转载于:https://www.cnblogs.com/f321dd/p/6744497.html

你可能感兴趣的:(BZOJ4860: [Beijing2017]树的难题)