洛谷3703 [SDOI2017] 树点染色 【LCT】【线段树】
题目分析:
操作一很明显等价于LCT上的access操作,操作二是常识,操作三转化到dfs序上求最大值也是常识。access的时候顺便在线段树中把对应部分-1,把右子树的子树+1即可。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 102000; 5 6 int num,n,m; 7 8 vector <int> g[maxn]; 9 10 int f[maxn],dep[maxn],dfsin[maxn],dfsout[maxn]; 11 12 class SegmentTree{ 13 private: 14 int data[maxn<<2],lazy[maxn<<2],maxx[maxn<<2]; 15 void push_down(int now){ 16 int L = (now<<1),R = (now<<1|1); 17 data[L] += lazy[now]; maxx[L] += lazy[now]; lazy[L] += lazy[now]; 18 data[R] += lazy[now]; maxx[R] += lazy[now]; lazy[R] += lazy[now]; 19 lazy[now] = 0; 20 } 21 public: 22 void Add(int now,int tl,int tr,int l,int r,int d){ 23 if(lazy[now]&&tl!=tr) push_down(now); 24 if(tl >= l && tr <= r){ 25 data[now] += d; lazy[now] += d;maxx[now] += d; return; 26 } 27 if(tl > r || tr < l) return; 28 int mid = (tl+tr)/2; 29 Add(now<<1,tl,mid,l,r,d); 30 Add(now<<1|1,mid+1,tr,l,r,d); 31 maxx[now] = max(maxx[now<<1],maxx[now<<1|1]); 32 } 33 int Query(int now,int tl,int tr,int l,int r){ 34 if(lazy[now]&&tl!=tr) push_down(now); 35 if(tl >= l && tr <= r) return maxx[now]; 36 if(tl > r || tr < l) return 0; 37 int mid = (tl+tr)/2; 38 int ans = max(Query(now<<1,tl,mid,l,r),Query(now<<1|1,mid+1,tr,l,r)); 39 maxx[now] = max(maxx[now<<1],maxx[now<<1|1]); 40 return ans; 41 } 42 }T; 43 44 class LinkCutTree{ 45 private: 46 int ch[maxn][2],fa[maxn],data[maxn]; 47 stack <int> sta; 48 49 int is_root(int now){return ch[fa[now]][0]!=now&&ch[fa[now]][1]!=now;} 50 51 void r0(int now,int dr){ 52 int son = ch[now][dr],pa = fa[now],gp = fa[pa]; 53 int tag = is_root(pa); 54 ch[pa][dr^1] = son; fa[son] = pa; 55 ch[now][dr] = pa; fa[pa] = now; fa[now] = gp; 56 if(tag == 1) return; 57 if(ch[gp][0] == pa) ch[gp][0] = now; 58 else ch[gp][1] = now; 59 } 60 61 void splay(int now){ 62 while(!is_root(now)){ 63 int pa = fa[now],gp = fa[pa]; 64 if(is_root(pa)){ 65 if(ch[pa][0] == now) r0(now,1); 66 else r0(now,0); 67 }else{ 68 if(ch[gp][0] == pa){ 69 if(ch[pa][0] == now) r0(pa,1),r0(now,1); 70 else r0(now,0),r0(now,1); 71 }else{ 72 if(ch[pa][0] == now) r0(now,1),r0(now,0); 73 else r0(pa,0),r0(now,0); 74 } 75 } 76 } 77 } 78 public: 79 void access(int now){ 80 int p = now,last = 0; 81 while(p != 0){ 82 splay(p); 83 int zz = ch[p][1]; while(ch[zz][0]) zz = ch[zz][0]; 84 if(zz)T.Add(1,1,n,dfsin[zz],dfsout[zz],1); 85 int lt = p; while(ch[lt][0]) lt = ch[lt][0]; 86 T.Add(1,1,n,dfsin[lt],dfsout[lt],-1); 87 ch[p][1] = last; 88 last = p; p = fa[p]; 89 } 90 T.Add(1,1,n,1,n,1); 91 } 92 void BuildLCT(){ 93 for(int i=1;i<=n;i++) data[i] = dep[i]; 94 for(int i=1;i<=n;i++) fa[i] = f[i]; 95 } 96 }LCT; 97 98 void read(){ 99 scanf("%d%d",&n,&m); 100 for(int i=1;i<n;i++){ 101 int u,v; scanf("%d%d",&u,&v); 102 g[u].push_back(v); g[v].push_back(u); 103 } 104 } 105 106 int RMQ[maxn<<1][20],app[maxn][2],euler[maxn<<1],nE; 107 108 void dfs(int now,int fa,int dp){ 109 f[now] = fa; dep[now] = dp; 110 euler[++nE] = now; app[now][0] = app[now][1] = nE; 111 dfsin[now] = dfsout[now] = ++num; 112 T.Add(1,1,n,dfsin[now],dfsin[now],dp); 113 for(int i=0;i<g[now].size();i++){ 114 int p = g[now][i]; 115 if(p == fa) continue; 116 dfs(p,now,dp+1); 117 dfsout[now] = dfsout[p]; 118 euler[++nE] = now; app[now][1] = nE; 119 } 120 } 121 122 void BuildRMQ(){ 123 for(int i=1;i<=nE;i++) RMQ[i][0] = euler[i]; 124 for(int k=1;(1<<k)<=nE;k++){ 125 for(int i=1;i<=nE;i++){ 126 if(i+(1<<k-1) > nE) {RMQ[i][k] = RMQ[i][k-1];continue;} 127 if(dep[RMQ[i][k-1]] < dep[RMQ[i+(1<<k-1)][k-1]]){ 128 RMQ[i][k] = RMQ[i][k-1]; 129 }else RMQ[i][k] = RMQ[i+(1<<k-1)][k-1]; 130 } 131 } 132 } 133 134 int QueryLCA(int u,int v){ 135 int fst = min(app[u][0],app[v][0]),sec = max(app[u][1],app[v][1]); 136 int len = sec-fst+1,k = 0; 137 while((1<<k+1) <= len) k++; 138 if(dep[RMQ[fst][k]] < dep[RMQ[sec-(1<<k)+1][k]]) return RMQ[fst][k]; 139 else return RMQ[sec-(1<<k)+1][k]; 140 } 141 142 void init(){ 143 dfs(1,0,1); 144 BuildRMQ(); 145 LCT.BuildLCT(); 146 } 147 148 void getdist(){ 149 int u,v; scanf("%d%d",&u,&v); 150 int lca = QueryLCA(u,v); 151 u = dfsin[u],v = dfsin[v],lca = dfsin[lca]; 152 int ans = T.Query(1,1,n,u,u)+T.Query(1,1,n,v,v); 153 ans = ans - 2*T.Query(1,1,n,lca,lca) + 1; 154 printf("%d\n",ans); 155 } 156 157 void Query(){ 158 int u; scanf("%d",&u); 159 int ans = T.Query(1,1,n,dfsin[u],dfsout[u]); 160 printf("%d\n",ans); 161 } 162 163 void work(){ 164 for(int i=1;i<=m;i++){ 165 int cas; scanf("%d",&cas); 166 if(cas == 1){int x;scanf("%d",&x);LCT.access(x);} 167 else if(cas == 2) getdist(); 168 else if(cas == 3) Query(); 169 } 170 } 171 172 int main(){ 173 read(); 174 init(); 175 work(); 176 return 0; 177 }