bzoj 4860 [BeiJing2017]樹的難題

題面

https://www.lydsy.com/JudgeOnline/problem.php?id=4860php

題解

點分治node

設當前重心爲vgit

假設已經把全部邊按照出發點第一關鍵字, 顏色第二關鍵字排序ide

對於當前的v 咱們順次考慮他的出邊spa

設當前出邊(v,nw) 顏色 colcode

咱們枚舉nw的出邊blog

對於一條nw的出邊而言, 分爲兩種狀況排序

1. 顏色與col相同   用線段樹維護深度及對應的最值,查詢到最大值便可 (v,nw)沒有貢獻隊列

2. 顏色與col不一樣   用另外一棵線段樹維護深度以及與(當前節點的連向其父節點的邊的顏色)不一樣的(連向子節點的邊)所對應的子節點對應的子樹以內的最值 加上col的權值get

向上的時候 將線段樹合併

Code

 1 #include <cstdio>
 2 #include <cctype>
 3 #include <algorithm>
 4 const int maxn=400010,inf=2000000010;  5 int ans,n,x,y,z,i,m,l,r,c[maxn*3],cnt;  6 inline int max(int a,int b){  7     return a>b?a:b;  8 }  9 inline void up(int&a,const int&b){  10     if(a<b)a=b;  11 }  12 inline int getint(){  13     char c=getchar();  14     int x=0,neg=1;  15     while(!isdigit(c)){  16         if(c=='-')neg=-1;  17         c=getchar();  18  }  19     while(isdigit(c)){  20         x=x*10+c-48;  21         c=getchar();  22  }  23     return x*neg;  24 }  25 struct edge{  26     int from,to,color;  27 }e[maxn<<1];  28 struct data{  29     int dep,sum;  30 };  31 struct node{  32     int v,lc,rc;  33 }a[maxn*5];  34 int merge(int x,int y){  35     if(!x || !y )return x|y;  36     a[x].lc=merge(a[x].lc,a[y].lc);  37     a[x].rc=merge(a[x].rc,a[y].rc);  38  up(a[x].v,a[y].v);  39     return x;  40 }  41 void add(int&i,int rl,int rr,int x,int v){  42     if(!i)a[i=++cnt]=(node){v,0,0};  43         else up(a[i].v,v);  44     if(rl<rr){  45         int m=(rl+rr)>>1;  46         if(x>m)add(a[i].rc,m+1,rr,x,v);  47             else add(a[i].lc,rl,m,x,v);  48  }  49 }  50 int query(int i,int rl,int rr,int l,int r){  51     if(!i)return -inf;  52     if(rl==l && rr==r)return a[i].v;  53     int m=(rl+rr)>>1;  54     if(l>m)return query(a[i].rc,m+1,rr,l,r);  55         else if(r<=m)return query(a[i].lc,rl,m,l,r);  56             else return max(query(a[i].lc,rl,m,l,m),query(a[i].rc,m+1,rr,m+1,r));  57 }  58 struct tree{  59     int xb,h[maxn],n,size[maxn],f[maxn],rt,sum,dep[maxn],ll,ss[maxn];  60     bool b[maxn];  61  data w[maxn];  62     void addedge(int x,int y,int z){  63         e[++xb]=(edge){y,x,z};  64         e[++xb]=(edge){x,y,z};  65  }  66     void dfs(int x,int fa){  67         size[x]=f[x]=1;  68         for(int i=h[x];i<h[x+1];++i){  69             int y=e[i].to;  70             if(y!=fa && !b[y]){  71  dfs(y,x);  72                 size[x]+=size[y];  73  up(f[x],size[y]);  74  }  75  }  76         up(f[x],sum-size[x]);  77         if(f[rt]>f[x])rt=x;  78  }  79     void got(int x,int fa,int dep,int color,int sum){  80         for(int y,i=h[x];i<h[x+1];++i){  81             y=e[i].to;  82             if(y!=fa && !b[y]){  83                 if(e[i].color==color)w[++ll]=(data){dep+1,sum};  84                     else w[++ll]=(data){dep+1,sum+c[e[i].color]};  85                 got(e[i].to,x,dep+1,e[i].color,w[ll].sum);  86  }  87  }  88  }  89     void solve(int x){  90         b[x]=1;  91         int i,rt1=0,rt2=cnt=0,j;  92         for(i=h[x];i<h[x+1];++i){  93             if(i>h[x] && e[i].color>e[i-1].color)rt1=merge(rt1,rt2),rt2=0;  94             if(!b[e[i].to]){  95                 w[ll=1]=(data){1,c[e[i].color]};  96                 got(e[i].to,x,1,e[i].color,c[e[i].color]);  97                 ss[i]=ll;  98                 for(j=1;j<=ll;++j)if(w[j].dep<=r){  99                     if(w[j].dep>=l)up(ans,w[j].sum); 100                     if(w[j].dep<r){ 101                         up(ans,query(rt1,1,n,max(1,l-w[j].dep),r-w[j].dep)+w[j].sum); 102                         up(ans,query(rt2,1,n,max(1,l-w[j].dep),r-w[j].dep)-c[e[i].color]+w[j].sum); 103  } 104  } 105                 for(j=1;j<=ll;++j)if(w[j].dep<=r)add(rt2,1,n,w[j].dep,w[j].sum); 106  } 107  } 108         for(i=h[x];i<h[x+1];++i) 109             if(!b[e[i].to]){ 110                 sum=ss[i]; 111                 rt=0; 112  dfs(e[i].to,x); 113  solve(rt); 114  } 115  } 116 }t; 117 bool cmp(const edge&a,const edge&b){ 118     return a.from==b.from?a.color<b.color:a.from<b.from; 119 } 120 int main(){ 121     //freopen("input","r",stdin);
122     a[0].v=-inf; 123     t.n=n=getint(); 124     m=getint(); 125     l=getint(); 126     r=getint(); 127     for(i=1;i<=m;++i)c[i]=getint(); 128     for(i=1;i<n;++i){ 129         x=getint(); 130         y=getint(); 131         z=getint(); 132  t.addedge(x,y,z); 133  } 134     std::sort(e+1,e+((n-1)*2)+1,cmp); 135     for(i=1;i<=((n-1)<<1);++i) 136         if(!t.h[e[i].from])t.h[e[i].from]=i; 137     t.h[n+1]=(n-1)<<1|1; 138     t.f[t.rt=0]=inf; 139     t.sum=n; 140     ans=-inf; 141     t.dfs(1,0); 142  t.solve(t.rt); 143     printf("%d\n",ans); 144 }
View Code

Review

一開始覺得是樹形dp 後來發現那是錯的

還能夠用單調隊列過 好像更簡單

相關文章
相關標籤/搜索