zoukankan      html  css  js  c++  java
  • bzoj 3779: 重组病毒

      一道好题~~

      一个点到根传染需要的时间是这段路径上不同颜色的数目,一个点子树到根平均传染时间就是加权平均数了(好像是废话)。

      所以只要用线段树维护dfs序就这个可以了,换根的话一个点的子树要么在dfs序中不变,要么被截成了[1,l)和(r,n]两段(当这个点为当前root的祖先),l和r即为包含当前根的这个点的那个儿子的dfs序中的st和ed,只要分类讨论一下就可以了。

      所以问题只剩什么时候在线段树上修改,我们发现1操作和LCT中的access操作很像,2操作就是make_root,每个splay就是一个相同的颜色段,那么一个点到根的距离就是LCT中虚边的个数,把虚边改实边子树-1,反过来子树+1,而LCT的复杂度是nlogn的,那直接做就好了。

      

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #define N 100005
      6 #define ll long long
      7 using namespace std;
      8 int head[N],nxt[N*2],ver[N*2],tot;int n,m;
      9 void addd(int a,int b)
     10 {
     11     tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ;
     12 }
     13 int rev[N],ch[N][2],root,L[N],R[N],fa[N],faa[N];
     14 bool isroot(int x)
     15 {
     16     return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
     17 }
     18 void push_down(int x)
     19 {
     20     if(rev[x])
     21     {
     22         rev[x]^=1;rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;
     23         swap(L[ch[x][0]],R[ch[x][0]]);
     24         swap(L[ch[x][1]],R[ch[x][1]]);
     25         swap(ch[x][0],ch[x][1]);
     26     }
     27     return ;
     28 }
     29 void push_up(int x)
     30 {
     31     if(!ch[x][0])L[x]=x;
     32     else L[x]=L[ch[x][0]];
     33     if(!ch[x][1])R[x]=x;
     34     else R[x]=R[ch[x][1]];
     35 }
     36 void rotate(int p)
     37 {
     38     int q=fa[p],y=fa[q],x=(ch[q][1]==p);
     39     ch[q][x]=ch[p][x^1];fa[ch[q][x]]=q;
     40     ch[p][x^1]=q;
     41     fa[p]=y;
     42     if(!isroot(q))
     43     {
     44         if(ch[y][1]==q)ch[y][1]=p;
     45         else ch[y][0]=p;
     46     }
     47     fa[q]=p;
     48     push_up(q);
     49 }
     50 int q[N],topp;
     51 void splay(int x)
     52 {
     53     q[++topp]=x;
     54     for(int i=x;!isroot(i);i=fa[i])q[++topp]=fa[i];
     55     while(topp)push_down(q[topp--]);
     56     for(int y;!isroot(x);rotate(x))
     57     {
     58         y=fa[x];
     59         if(!isroot(y))
     60         {
     61             if((ch[fa[y]][0]==y)^(ch[y][0]==x))rotate(x);
     62             else rotate(y);
     63         }
     64     }
     65     push_up(x);
     66 }
     67 struct node
     68 {
     69     ll lazy,sum;
     70 }a[N*10];
     71 int sz[N];
     72 int st[N],ed[N],z,jian[N],dep[N],top[N],son[N];
     73 int find(int x,int y)
     74 {
     75     while(top[y]!=top[x])
     76     {
     77         if(faa[top[y]]==x)return top[y];
     78         y=faa[top[y]];
     79     }
     80     return son[x];
     81 }
     82 void dfs(int x,int f)
     83 {
     84     st[x]=++z;jian[z]=dep[x];sz[x]=1;L[x]=R[x]=x;
     85     for(int i=head[x];i;i=nxt[i])
     86     {
     87         if(ver[i]==f)continue;
     88         fa[ver[i]]=x;dep[ver[i]]=dep[x]+1;faa[ver[i]]=x;
     89          
     90         dfs(ver[i],x);
     91         sz[x]+=sz[ver[i]];
     92         if(sz[ver[i]]>sz[son[x]])son[x]=ver[i];
     93     }
     94     ed[x]=z;
     95     return ;
     96 }
     97 void dffs(int x,int f,int tp)
     98 {
     99     top[x]=tp;
    100     if(son[x])dffs(son[x],x,tp);
    101     for(int i=head[x];i;i=nxt[i])
    102     {
    103         if(ver[i]==f||ver[i]==son[x])continue;
    104         dffs(ver[i],x,ver[i]);
    105     }
    106 }
    107 void pd(int x,int l,int mid,int r)
    108 {
    109     if(a[x].lazy)
    110     {
    111         a[x*2].sum+=a[x].lazy*(mid-l+1);
    112         a[x*2+1].sum+=a[x].lazy*(r-mid);
    113         a[x*2].lazy+=a[x].lazy;a[x*2+1].lazy+=a[x].lazy;
    114         a[x].lazy=0;
    115     }return ;
    116 }
    117 ll qur(int x,int l,int r,int lll,int rr)
    118 {
    119     if(rr<lll)return 0;
    120     if(lll<=l&&rr>=r)
    121     {
    122         return a[x].sum;
    123     }
    124     int mid=(l+r)>>1;
    125     pd(x,l,mid,r);
    126     if(lll>mid)return qur(x*2+1,mid+1,r,lll,rr);
    127     if(rr<=mid)return qur(x*2,l,mid,lll,rr);
    128     return qur(x*2,l,mid,lll,rr)+qur(x*2+1,mid+1,r,lll,rr);
    129 }
    130 void add(int x,int l,int r,int lll,int rr,ll z)
    131 {
    132     if(rr<lll)return ;
    133     if(lll<=l&&rr>=r)
    134     {
    135         a[x].sum+=z*(r-l+1);
    136         a[x].lazy+=z;
    137         return ;
    138     }
    139     int mid=(l+r)>>1;
    140     pd(x,l,mid,r);
    141     if(lll<=mid)add(x*2,l,mid,lll,rr,z);
    142     if(rr>mid)add(x*2+1,mid+1,r,lll,rr,z);
    143     a[x].sum=a[x*2].sum+a[x*2+1].sum;
    144 }
    145 void build(int x,int l,int r)
    146 {
    147     if(l==r)
    148     {
    149         a[x].sum=jian[l];
    150         return ;
    151     }
    152     int mid=(l+r)>>1;
    153     build(x*2,l,mid);build(x*2+1,mid+1,r);
    154     a[x].sum=a[x*2].sum+a[x*2+1].sum;
    155     return ;
    156 }
    157 void gao(int x,int z)
    158 {
    159     if(x==root)
    160     {
    161         add(1,1,n,1,n,z);
    162     }
    163     else if(st[x]<st[root]&&ed[x]>=ed[root])
    164     {
    165         int t=find(x,root);
    166         add(1,1,n,1,st[t]-1,z);
    167         add(1,1,n,ed[t]+1,n,z);
    168     }
    169     else
    170     {
    171         add(1,1,n,st[x],ed[x],z);
    172     }
    173 }
    174 void access(int x)
    175 {
    176     for(int t=0;x;t=x,x=fa[x])
    177     {
    178         splay(x);
    179         if(t)gao(L[t],-1);
    180         if(ch[x][1])
    181         {
    182             gao(L[ch[x][1]],1);
    183         }
    184         ch[x][1]=t;
    185         push_up(x);
    186     }
    187     return ;
    188 }
    189 void make_root(int x)
    190 {
    191     access(x);splay(x);
    192     rev[x]^=1;swap(L[x],R[x]);
    193     return ;
    194 }
    195 int qursize(int x)
    196 {
    197     if(x==root)return n;
    198     if(st[x]<st[root]&&ed[x]>=ed[root])
    199     {
    200         int t=find(x,root);
    201         return n-sz[t];
    202     }
    203     else return sz[x];
    204 }
    205 ll qurs(int x)
    206 {
    207     if(x==root)return qur(1,1,n,1,n);
    208     if(st[x]<st[root]&&ed[x]>=ed[root])
    209     {
    210         int t=find(x,root);
    211         return qur(1,1,n,1,st[t]-1)+qur(1,1,n,ed[t]+1,n);
    212     }
    213     return qur(1,1,n,st[x],ed[x]);
    214 }
    215 int main()
    216 {
    217     scanf("%d%d",&n,&m);
    218     int t1,t2;
    219     for(int i=1;i<n;i++)
    220     {
    221         scanf("%d%d",&t1,&t2);
    222         addd(t1,t2);addd(t2,t1);
    223     }
    224     dep[1]=1;
    225     dfs(1,-1);
    226     build(1,1,n);
    227     dffs(1,-1,1);
    228     char c[10];root=1;int tmp;
    229     for(int i=1;i<=m;i++)
    230     {
    231         scanf("%s",c+1);
    232         scanf("%d",&tmp);
    233         if(c[3]=='Q')
    234         {
    235             int size=qursize(tmp);
    236             ll ss=qurs(tmp);
    237             printf("%.10lf
    ",((double)ss)/size);
    238         }
    239         else if(c[3]=='L')
    240         {
    241             access(tmp);
    242              
    243         }
    244         else
    245         {   
    246             make_root(tmp);
    247             root=tmp;
    248         }
    249     }
    250     return 0;
    251 }

      

  • 相关阅读:
    HDU 5828 Rikka with Sequence (线段树+剪枝优化)
    Educational Codeforces Round 5 E. Sum of Remainders (思维题)
    HDU 2256 Problem of Precision (矩阵快速幂)
    Codeforces 597C. Subsequences (树状数组+dp)
    Codeforces Round #292 (Div. 1) B. Drazil and Tiles (类似拓扑)
    HDU 5794 A Simple Chess (Lucas + dp)
    Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum (离线树状数组+前缀xor)
    Codeforces Round #313 (Div. 2) E. Gerald and Giant Chess (Lucas + dp)
    进程内存空间的分布
    快排,堆排与归并排序
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6400727.html
Copyright © 2011-2022 走看看