BZOJ4860: [Beijing2017]树的难题
对于每个重心,每个子树可以求出一个数组,表示每个深度的答案。先同种颜色合并,再不同颜色合并。合并可以按高度从小到大排序,然后跑单调队列,复杂度$O(n\log n)$。我比较脑抽,写的是从大到小排序,然后跑线段树,复杂度$O(n\log^2 n)$。
#include<bits/stdc++.h>
#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;};
vector<info>e[N];
int ans=-inf;
int n,m,l,r,siz[N],w[N];
bool vis[N];
int len,f[N*4];
void pre(vector<int>&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<int>&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{
u<I?cov(u,v,i,J,P):cov(u,v,I,j,S);
f[k]=max(f[P],f[S]);
}
}
void cov(int u,int v){
cov(u,v,1,len,1);
}
int ask(int u,int v,int i,int j,int k){
return u==i&&j==v?f[k]:v<I?ask(u,v,i,J,P):u>J?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<int>&a,const vector<int>&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(d<r)
FOR(i,e[u])
if(i->v!=p&&!vis[i->v])
s=max(s,dfs4(i->v,u,d+1));
return s;
}
vector<int>cur;
void dfs5(int u,int p,int c,int d,int s){
cur[d]=max(cur[d],s);
if(d<r)
FOR(i,e[u])
if(i->v!=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<int,vector<vector<int> > >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<vector<int> >tmp;
FOR(i,col){
sort(RAN(i->second),cmp);
vector<int>&s=i->second.front();
pre(s);
FOR(j,i->second)
if(j!=i->second.begin()){
vector<int>&v=*j;
if(v.size()+len>=l)
for(int k=0;k<v.size();++k){
int a=ask(l-k-1,r-k-1);
if(a!=-inf)
ans=max(ans,a+v[k]-w[i->first]);
}
for(int k=0;k<v.size();++k){
cov(k+1,v[k]);
s[k]=max(s[k],v[k]);
}
}
ans=max(ans,ask(l,r));
tmp.pb(s);
}
if(tmp.size()>1){
sort(RAN(tmp),cmp);
pre(tmp.front());
FOR(i,tmp)
if(i!=tmp.begin()){
vector<int>&v=*i;
if(v.size()+len>=l)
for(int j=0;j<v.size();++j){
int a=ask(l-j-1,r-j-1);
if(a!=-inf)
ans=max(ans,a+v[j]);
}
for(int j=0;j<v.size();++j)
cov(j+1,v[j]);
}
}
FOR(i,e[u])
if(!vis[i->v])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);
}

浙公网安备 33010602011771号