#include <iostream> #include <stdio.h> #include <vector> #include <algorithm> #include <cstring> #include <queue> using namespace std; typedef long long LL; const int MAX_N = 2e5 +6; const int MAX_P = 19; vector<int> edg[MAX_N]; int depth[MAX_N]; int p[MAX_N]; int lca[MAX_P][MAX_N]; int pin[MAX_N],pout[MAX_N]; int sz[MAX_N]; int stamp; void dfs(int id,int p,int cur_depth) { lca[0][id] = p; depth[id] = cur_depth; pin[id] = stamp++; sz[id] = 1; for (int i:edg[id]) { if (i!=p) { dfs(i,id,cur_depth+1); sz[id] += sz[i]; } } pout[id] = stamp++; } bool is_anc(int parent,int son ){ return pin[parent] <= pin[son] && pout[son] <= pout[parent]; } int get_lca(int a,int b) { if (depth[a] > depth[b]) swap(a,b); if (is_anc(a,b)) return a; int bb=b; for (int i=MAX_P-1;i>=0;i--) { if (!is_anc(lca[i][b],a)) b=lca[i][b]; } b=lca[0][b]; return b; } LL seg[4*MAX_N]; int tag[4*MAX_N]; void push(int id,int L,int R) { if (L==R) tag[id]=0; if (tag[id]==0) return; tag[id*2] += tag[id]; tag[id*2+1] += tag[id]; int mid=(L+R)>>1; seg[id*2] += tag[id]*(mid-L+1); seg[id*2+1] += tag[id]*(R-mid); tag[id]=0; return; } void modify(int id,int L,int R,int l,int r,int val) { if (l>R || L>r) return; else if (l<=L && R<=r) { tag[id] += val; seg[id] += (R-L+1)*val; return; } push(id,L,R); int mid=(L+R)>>1; if (mid + 1 > r) modify(id*2,L,mid,l,r,val); else if (l > mid) modify(id*2+1,mid+1,R,l,r,val); else { modify(id*2,L,mid,l,r,val); modify(id*2+1,mid+1,R,l,r,val); } seg[id] = seg[id*2] + seg[id*2+1]; } LL query(int id,int L,int R,int l,int r){ if (l>R || L>r) return 0; else if (l<=L && R<=r) return seg[id]; push(id,L,R); int mid=(L+R)>>1; if (mid + 1 > r) return query(id*2,L,mid,l,r); else if (l > mid) return query(id*2+1,mid+1,R,l,r); else { return query(id*2,L,mid,l,r) + query(id*2+1,mid+1,R,l,r); } } #define SZ(x) ((int)(x).size()) int head[MAX_N]; int tin[MAX_N]; int n,m; void dfs2(int id,int p,bool nnew) { sort(edg[id].begin(),edg[id].end(),[](const int &a,const int &b) { return sz[a] >sz[b]; }); if (nnew) { head[id] = id; } else { head[id] = head[p]; } tin[id] = ++stamp; bool gett=false; for (int ii=0;SZ(edg[id])>ii;ii++) { int i=edg[id][ii]; if (i==p) continue; dfs2(i,id,gett); gett=true; } } LL Q(int son,int parent) { if (son == parent) return 0; LL ret=0; while (head[son] != head[parent]) { //son --> head[son] ret += query(1,1,n,tin[head[son]],tin[son]); son = head[son]; son = lca[0][son]; } if (son == parent) return ret+0; else return ret+query(1,1,n,tin[parent]+1,tin[son]); } void change(int son,int parent) { if (son == parent) return; while (head[son] != head[parent]) { //son --> head[son] modify(1,1,n,tin[head[son]],tin[son],1); son = head[son]; son = lca[0][son]; } if (son == parent) return; else modify(1,1,n,tin[parent]+1,tin[son],1); } int main () { scanf("%d %d",&n,&m); for (int i=1;n>i;i++) { int a,b; scanf("%d %d",&a,&b); edg[a].push_back(b); edg[b].push_back(a); } stamp=0; dfs(1,1,1); for (int i=1;MAX_P>i;i++) { for (int j=1;n>=j;j++) { lca[i][j] = lca[i-1][lca[i-1][j]]; } } stamp=0; dfs2(1,1,1); for (int i=1;m>=i;i++) { getchar(); char c; int a,b; scanf("%c %d %d",&c,&a,&b); int lca = get_lca(a,b); if (c=='P') { change(a,lca); change(b,lca); } else if (c=='Q') { printf("%lld\n",Q(a,lca) + Q(b,lca)); } } }
2017年8月18日 星期五
(Sky OJ) 146. Day 3 PH. 樹樹鏈鏈剖剖分分 [樹鏈剖分]
https://pc2.tfcis.org/sky/index.php/problem/view/146/
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言