3779: 重组病毒

Posted Achen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3779: 重组病毒相关的知识,希望对你有一定的参考价值。

传送门

一道很有奥妙的题.

发现修改操作和access有着不可不说的关系.

因为操作的特殊性,每种颜色在树上是一段连续的区间.不会被切开.

若x跟父亲颜色相同,设x到父亲的边的权值为0,否则为1

那么一个点到根的颜色就是它到跟路径上1的个数+1

修改从x到根,x到根的边全都变成0,x到跟路径上相邻的其他边都变成1

把1看成虚边,0看出实边,就相当于access操作

用lct维护即可得到每次需要修改的边,修改一条边相当于子树修改,线段树维护dfs序即可

newroot时候不需要单独处理,只需access的时候加减.注意access的时候加减的是rc/t那颗splay中深度最浅的节点,不是rc/t本身

查询修改都同遥远的国度,分类讨论.(注意修改也要讨论呀...你是改子树呀...)

然后观察了一下别人的代码,发现找我包含根的那个儿子不应该暴力枚举我的儿子而应该预处理倍增数组从根跳,,改了一下..虽然数据也不卡我...

 

技术分享图片
  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<cmath>
 10 #include<set>
 11 #include<map>
 12 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 14 const int N=3e5+7;
 15 typedef long long LL; 
 16 typedef double db;
 17 using namespace std;
 18 int n,m,rt;
 19 char o[15];
 20 
 21 template<typename T> void read(T &x) {
 22     char ch=getchar(); x=0; T f=1;
 23     while(ch!=-&&(ch<0||ch>9)) ch=getchar();
 24     if(ch==-) f=-1,ch=getchar();
 25     for(;ch>=0&&ch<=9;ch=getchar()) x=x*10+ch-0; x*=f;
 26 }
 27 
 28 int ecnt,fir[N],nxt[N<<1],to[N<<1];
 29 void add(int u,int v) {
 30     nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
 31     nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
 32 }
 33 
 34 LL sg[N<<2],lz[N<<2];
 35 #define ls x<<1
 36 #define rs ((x<<1)|1)
 37 #define mid ((l+r)>>1)
 38 void down(int x,int l_len,int r_len) {
 39     if(!lz[x]) return;
 40     if(l_len) sg[ls]=sg[ls]+l_len*lz[x],lz[ls]=lz[ls]+lz[x];
 41     if(r_len) sg[rs]=sg[rs]+r_len*lz[x],lz[rs]=lz[rs]+lz[x];
 42     lz[x]=0;
 43 }
 44  
 45 void update(int x,int l,int r,int ql,int qr,int v) {
 46     if(ql>qr) return;
 47     if(l>=ql&&r<=qr) {
 48         sg[x]=sg[x]+(LL)(r-l+1)*v;
 49         lz[x]=lz[x]+v; return;
 50     }
 51     down(x,mid-l+1,r-mid);
 52     if(ql<=mid) update(ls,l,mid,ql,qr,v);
 53     if(qr>mid) update(rs,mid+1,r,ql,qr,v);
 54     sg[x]=sg[ls]+sg[rs];
 55 }
 56 
 57 LL qry(int x,int l,int r,int ql,int qr) {
 58     if(ql>qr) return 0;
 59     if(l>=ql&&r<=qr) return sg[x];
 60     down(x,mid-l+1,r-mid);
 61     if(qr<=mid) return qry(ls,l,mid,ql,qr);
 62     if(ql>mid) return qry(rs,mid+1,r,ql,qr);
 63     return qry(ls,l,mid,ql,qr)+qry(rs,mid+1,r,ql,qr);
 64 }
 65 
 66 int p[N],ch[N][2],flip[N],st[N][20];
 67 
 68 int sz[N],fa[N],dfn[N],R[N],dfs_clock;
 69 void dfs(int x,int FA) {
 70     sz[x]=1;
 71     p[x]=FA;
 72     fa[x]=FA;
 73     st[x][0]=FA;
 74     For(i,1,19) st[x][i]=st[st[x][i-1]][i-1];
 75     R[x]=R[FA]+1;
 76     dfn[x]=++dfs_clock;
 77     update(1,1,n,dfn[x],dfn[x],R[x]);
 78     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=FA) {
 79         dfs(to[i],x);
 80         sz[x]+=sz[to[i]];
 81     }
 82 }
 83 
 84 #define lc ch[x][0]
 85 #define rc ch[x][1]
 86 
 87 void down(int x) {
 88     if(!flip[x]) return;
 89     swap(lc,rc);
 90     flip[lc]^=1;
 91     flip[rc]^=1;
 92     flip[x]^=1;
 93 }
 94 
 95 int isroot(int x) { return ch[p[x]][0]!=x&&ch[p[x]][1]!=x; }
 96 
 97 void rotate(int x) {
 98     int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
 99     if(!isroot(y)) ch[z][y==ch[z][1]]=x; p[x]=z;
100     ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
101     ch[x][r]=y; p[y]=x;
102 }
103 
104 void splay(int x) {
105     static int g[N],top=0,tp;
106     for(tp=x;!isroot(tp);tp=p[tp]) g[++top]=tp;
107     g[++top]=tp;
108     while(top) down(g[top--]);
109     for(;!isroot(x);rotate(x)) {
110         int y=p[x],z=p[y];
111         if(!isroot(y)) ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y);
112     }
113 }
114 
115 void change(int x,int v) {
116     if(x==rt) update(1,1,n,1,n,v);
117     else if(dfn[rt]>dfn[x]&&dfn[rt]<dfn[x]+sz[x]) {
118         int y=rt;
119         Rep(i,19,0) if(R[st[y][i]]>R[x]) y=st[y][i];
120            /*for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa[x]) {
121             y=to[i];
122             if(dfn[rt]>=dfn[y]&&dfn[rt]<dfn[y]+sz[y]) break;
123         } */
124         update(1,1,n,1,dfn[y]-1,v);
125         update(1,1,n,dfn[y]+sz[y],n,v);
126        }
127        else update(1,1,n,dfn[x],dfn[x]+sz[x]-1,v);
128 }
129 
130 void access(int x) {
131     for(int t=0;x;x=p[t=x]) {
132         splay(x);
133         if(rc) {
134             int tp=rc; down(tp); while(ch[tp][0]) { tp=ch[tp][0]; down(tp); }
135             change(tp,1); //shi bian xu
136         }
137         if(t) {
138             int tp=t; down(tp); while(ch[tp][0]) { tp=ch[tp][0]; down(tp); }
139             change(tp,-1); // xu bian shi
140         }
141         rc=t;
142     }
143 }
144 
145 void newroot(int x) {
146     access(x);
147     splay(x);
148     flip[x]^=1;
149     rt=x;
150 }
151 
152 void solve(int x) {
153     db ans=0.0;
154     if(x==rt) ans=(db)sg[1]/(1.0*n);
155     else if(dfn[rt]>dfn[x]&&dfn[rt]<dfn[x]+sz[x]) {
156         /*int y=0;
157            for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa[x]) {
158             y=to[i];
159             if(dfn[rt]>=dfn[y]&&dfn[rt]<dfn[y]+sz[y]) break;
160         }*/
161         int y=rt;
162         Rep(i,19,0) if(R[st[y][i]]>R[x]) y=st[y][i];
163         ans=((db)qry(1,1,n,1,dfn[y]-1)+qry(1,1,n,dfn[y]+sz[y],n))/(1.0*(n-sz[y]));
164        }
165        else ans=(db)qry(1,1,n,dfn[x],dfn[x]+sz[x]-1)/(1.0*sz[x]);
166     printf("%.10lf\n",ans);
167 }
168 
169 //#define DEBUG
170 int main() {
171 #ifdef DEBUG
172     freopen("3779.in","r",stdin);
173     freopen("3779.out","w",stdout);
174 #endif
175     read(n); read(m); rt=1;
176     For(i,2,n) { 
177         int x,y;
178         read(x); read(y);
179         add(x,y);
180     }
181     dfs(rt,0);
182     For(ti,1,m) {
183         int x;
184         scanf("%s",o); read(x);
185         if(o[2]==L) access(x);
186         else if(o[2]==C) newroot(x);
187         else if(o[2]==Q) solve(x);
188     }
189     return 0;
190 }
View Code

 

以上是关于3779: 重组病毒的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3779 重组病毒 LCT+线段树(维护DFS序)

3779: 重组病毒

bzoj 3779 重组病毒——LCT维护子树信息

bzoj 3779 重组病毒 —— LCT+树状数组(区间修改+区间查询)

bzoj4817[Sdoi2017]树点涂色&&bzoj3779-重组病毒

bzoj3779重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询