1. 程式人生 > >BZOJ4817: [Sdoi2017]樹點塗色(LCT)

BZOJ4817: [Sdoi2017]樹點塗色(LCT)

Description

Bob有一棵n個點的有根樹,其中1號點是根節點。Bob在每個點上塗了顏色,並且每個點上的顏色不同。定義一條路 徑的權值是:這條路徑上的點(包括起點和終點)共有多少種不同的顏色。Bob可能會進行這幾種操作: 1 x: 把點x到根節點的路徑上所有的點染上一種沒有用過的新顏色。 2 x y: 求x到y的路徑的權值。 3 x 在以x為根的子樹中選擇一個點,使得這個點到根節點的路徑權值最大,求最大權值。 Bob一共會進行m次操作

Input

第一行兩個數n,m。
接下來n-1行,每行兩個數a,b,表示a與b之間有一條邊。 接下來m行,表示操作,格式見題目描述 1<=n,m<=100000

Output

每當出現2,3操作,輸出一行。 如果是2操作,輸出一個數表示路徑的權值 如果是3操作,輸出一個數表示權值的最大值  

Sample Input

5 6
1 2
2 3
3 4
3 5
2 4 5
3 3
1 4
2 4 5
1 5
2 4 5

Sample Output

3
4
2
2

解題思路:

LCT好題access構造。

將第一個操作視為access操作並更新答案。

那麼開始時視為沒有輕重鏈。

access過程中若發生輕重鏈轉化時將子樹答案都加1,並撤銷上一節點操作。

這樣就可以在每一個節點上維護到根的權值和。

第三問直接解決。

第二問呢,發現合併兩條鏈的代價就是兩個鏈單獨的代價-2*lca代價+1(因為lca節點需要考慮)

子樹修改普通Dfs就好了。

程式碼:

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll tr[spc].ch[0]
  5
#define rrr tr[spc].ch[1] 6 #define ls ch[0] 7 #define rs ch[1] 8 typedef long long lnt; 9 const int N=300000; 10 struct seg_trnt{ 11 int lzt; 12 int maxval; 13 }ter[N<<2]; 14 struct spl_trnt{ 15 int ch[2]; 16 int fa; 17 int lzt; 18 bool anc; 19 }tr[N]; 20 struct pnt{ 21 int hd; 22 int dp; 23 int ind; 24 int oud; 25 int fa[20]; 26 }p[N]; 27 struct ent{ 28 int twd; 29 int lst; 30 }e[N<<1]; 31 int n,m; 32 int cnt; 33 int dfn; 34 bool sta=true; 35 int pos[N]; 36 void pushup(int spc) 37 { 38 ter[spc].maxval=std::max(ter[spc<<1].maxval,ter[spc<<1|1].maxval); 39 return ; 40 } 41 void ppushdown(int spc) 42 { 43 if(ter[spc].lzt) 44 { 45 ter[spc<<1].maxval+=ter[spc].lzt; 46 ter[spc<<1|1].maxval+=ter[spc].lzt; 47 ter[spc<<1].lzt+=ter[spc].lzt; 48 ter[spc<<1|1].lzt+=ter[spc].lzt; 49 ter[spc].lzt=0; 50 } 51 return ; 52 } 53 void update(int l,int r,int ll,int rr,int spc,int v) 54 { 55 if(ll>r||l>rr) 56 return ; 57 if(ll<=l&&r<=rr) 58 { 59 ter[spc].maxval+=v; 60 ter[spc].lzt+=v; 61 return ; 62 } 63 ppushdown(spc); 64 int mid=(l+r)>>1; 65 update(l,mid,ll,rr,spc<<1,v); 66 update(mid+1,r,ll,rr,spc<<1|1,v); 67 pushup(spc); 68 return ; 69 } 70 int maxq(int l,int r,int ll,int rr,int spc) 71 { 72 if(ll>r||l>rr) 73 return -0x3f3f3f3f; 74 if(ll<=l&&r<=rr) 75 return ter[spc].maxval; 76 int mid=(l+r)>>1; 77 ppushdown(spc); 78 return std::max(maxq(l,mid,ll,rr,spc<<1),maxq(mid+1,r,ll,rr,spc<<1|1)); 79 } 80 int query(int l,int r,int pos,int spc) 81 { 82 if(l==r) 83 return ter[spc].maxval; 84 ppushdown(spc); 85 int mid=(l+r)>>1; 86 if(pos<=mid) 87 return query(l,mid,pos,spc<<1); 88 return query(mid+1,r,pos,spc<<1|1); 89 } 90 void build(int l,int r,int spc) 91 { 92 if(l==r) 93 { 94 ter[spc].maxval=p[pos[l]].dp; 95 return ; 96 } 97 int mid=(l+r)>>1; 98 build(l,mid,spc<<1); 99 build(mid+1,r,spc<<1|1); 100 pushup(spc); 101 return ; 102 } 103 void ade(int f,int t) 104 { 105 cnt++; 106 e[cnt].twd=t; 107 e[cnt].lst=p[f].hd; 108 p[f].hd=cnt; 109 return ; 110 } 111 void dfs(int x,int f) 112 { 113 p[x].dp=p[f].dp+1; 114 p[x].fa[0]=f; 115 pos[++dfn]=x; 116 p[x].ind=dfn; 117 for(int i=1;i<=19;i++) 118 p[x].fa[i]=p[p[x].fa[i-1]].fa[i-1]; 119 for(int i=p[x].hd;i;i=e[i].lst) 120 { 121 int to=e[i].twd; 122 if(to==f) 123 continue; 124 tr[to].fa=x; 125 dfs(to,x); 126 } 127 p[x].oud=dfn; 128 return ; 129 } 130 int Lca(int x,int y) 131 { 132 if(p[x].dp<p[y].dp) 133 std::swap(x,y); 134 for(int i=19;i>=0;i--) 135 { 136 if(p[p[x].fa[i]].dp>=p[y].dp) 137 x=p[x].fa[i]; 138 } 139 if(x==y) 140 return x; 141 for(int i=19;i>=0;i--) 142 { 143 if(p[x].fa[i]!=p[y].fa[i]) 144 x=p[x].fa[i],y=p[y].fa[i]; 145 } 146 return p[x].fa[0]; 147 } 148 bool whc(int spc) 149 { 150 return tr[tr[spc].fa].rs==spc; 151 } 152 void trr(int spc) 153 { 154 if(!spc) 155 return ; 156 std::swap(lll,rrr); 157 tr[spc].lzt^=1; 158 return ; 159 } 160 void pushdown(int spc) 161 { 162 if(tr[spc].lzt) 163 { 164 tr[spc].lzt=0; 165 trr(lll); 166 trr(rrr); 167 } 168 return ; 169 } 170 void recal(int spc) 171 { 172 if(!tr[spc].anc) 173 recal(tr[spc].fa); 174 pushdown(spc); 175 return ; 176 } 177 void rotate(int spc) 178 { 179 int f=tr[spc].fa; 180 bool k=whc(spc); 181 tr[f].ch[k]=tr[spc].ch[!k]; 182 tr[spc].ch[!k]=f; 183 if(tr[f].anc) 184 { 185 tr[f].anc=0; 186 tr[spc].anc=1; 187 }else 188 tr[tr[f].fa].ch[whc(f)]=spc; 189 tr[spc].fa=tr[f].fa; 190 tr[f].fa=spc; 191 tr[tr[f].ch[k]].fa=f; 192 return ; 193 } 194 void splay(int spc) 195 { 196 recal(spc); 197 while(!tr[spc].anc) 198 { 199 int f=tr[spc].fa; 200 if(tr[f].anc) 201 { 202 rotate(spc); 203 return ; 204 } 205 if(whc(spc)^whc(f)) 206 rotate(spc); 207 else 208 rotate(f); 209 rotate(spc); 210 } 211 return ; 212 } 213 int leftpos(int spc) 214 { 215 pushdown(spc); 216 while(lll) 217 { 218 spc=lll; 219 pushdown(spc); 220 } 221 return spc; 222 } 223 void access(int spc) 224 { 225 int lst=0,x; 226 while(spc) 227 { 228 splay(spc); 229 tr[lst].anc=0; 230 tr[rrr].anc=1; 231 x=leftpos(rrr); 232 if(x&&!sta) 233 update(1,n,p[x].ind,p[x].oud,1,1); 234 x=leftpos(lst); 235 if(x&&!sta) 236 update(1,n,p[x].ind,p[x].oud,1,-1); 237 rrr=lst; 238 lst=spc; 239 spc=tr[spc].fa; 240 } 241 return ; 242 } 243 void Mtr(int spc) 244 { 245 access(spc); 246 splay(spc); 247 trr(spc); 248 return ; 249 } 250 void split(int x,int y) 251 { 252 Mtr(x); 253 access(y); 254 splay(y); 255 return ; 256 } 257 void link(int x,int y) 258 { 259 split(x,y); 260 tr[x].fa=y; 261 return ; 262 } 263 int main() 264 { 265 scanf("%d%d",&n,&m); 266 for(int i=1;i<=n;i++) 267 { 268 tr[i].anc=true; 269 } 270 for(int i=1;i<n;i++) 271 { 272 int a,b; 273 scanf("%d%d",&a,&b); 274 ade(a,b); 275 ade(b,a); 276 } 277 dfs(1,1); 278 build(1,n,1); 279 sta=false; 280 while(m--) 281 { 282 int cmd; 283 scanf("%d",&cmd); 284 if(cmd==1) 285 { 286 int x; 287 scanf("%d",&x); 288 Mtr(1); 289 access(x); 290 }else if(cmd==2) 291 { 292 int ans=1; 293 int x,y; 294 scanf("%d%d",&x,&y); 295 int z=Lca(x,y); 296 ans+=query(1,n,p[x].ind,1); 297 ans+=query(1,n,p[y].ind,1); 298 ans-=query(1,n,p[z].ind,1)<<1; 299 printf("%d\n",ans); 300 }else{ 301 int x; 302 scanf("%d",&x); 303 printf("%d\n",maxq(1,n,p[x].ind,p[x].oud,1)); 304 } 305 } 306 return 0; 307 }