洛谷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 }

 

posted @ 2018-05-29 21:49  menhera  阅读(207)  评论(0编辑  收藏  举报