• 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
    ",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
  • 相关阅读:
    类的特殊获取方式——《Thinking in Java》随笔008
    方法排序规范——《Thinking in Java》随笔007
    权限修饰符(访问指示符)——《Thinking in Java》随笔006
    史上最强,万能类型:Object——《Thinking in Java》随笔005
    七天C#小结
    编译原理10 消除左递归
    编译原理9 DFA最小化,语法分析初步
    编译原理8 非确定的自动机NFA确定化为DFA
    编译原理7 正规式、正规文法与自动机
    编译原理6 正规文法与正规式
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8982689.html
Copyright © 2020-2023  润新知