(WC2016模拟十八)Gangsters of Treeland

HINT:

$1\leq N,Q\leq 10^5$

原题:CodeChef November Challenge 2013 - MONOPLOY

题解:

其实这题是【SDOI2017】树点涂色的弱化版。。。

然后树点涂色这题甚至是[LOJ6022]【BZOJ3779】重组病毒的弱化版。。。

首先题目中的距离就是求路径上不同颜色的数目;

容易发现修改操作看起来很像LCT里的轻重边切换,那么以dfs序为下标建一颗线段树维护每个点到根节点的距离和,外面用一颗LCT维护,每次access轻重边切换的时候在线段树上修改即可。

时间复杂度:$O(nlog^2n)$

1A就是爽

代码:

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<cmath>
  6 #include<queue>
  7 #define inf 2147483647
  8 #define eps 1e-9
  9 using namespace std;
 10 typedef long long ll;
 11 struct edge{
 12     int v,next;
 13 }a[200001];
 14 int n,q,u,v,x,tim=0,tot=0,head[100001],dep[100001],siz[100001],in[100001],out[100001],nmd[100001];
 15 char op[3];
 16 namespace sgt{
 17     struct node{
 18         ll v,laz;
 19     }t[500001];
 20     void pd(int u,int l,int r){
 21         if(t[u].laz){
 22             int mid=(l+r)/2;
 23             t[u*2].v+=t[u].laz*(mid-l+1);
 24             t[u*2].laz+=t[u].laz;
 25             t[u*2+1].v+=t[u].laz*(r-mid);
 26             t[u*2+1].laz+=t[u].laz;
 27             t[u].laz=0;
 28         }
 29     }
 30     void build(int l,int r,int u){
 31         if(l==r){
 32             t[u].v=dep[nmd[l]]-1;
 33             return;
 34         }
 35         int mid=(l+r)/2;
 36         build(l,mid,u*2);
 37         build(mid+1,r,u*2+1);
 38         t[u].v=t[u*2].v+t[u*2+1].v;
 39     }
 40     void updata(int l,int r,int u,int L,int R,ll v){
 41         if(L<=l&&r<=R){
 42             t[u].v+=v*(r-l+1);
 43             t[u].laz+=v;
 44             return;
 45         }
 46         int mid=(l+r)/2;
 47         pd(u,l,r);
 48         if(L<=mid)updata(l,mid,u*2,L,R,v);
 49         if(mid<R)updata(mid+1,r,u*2+1,L,R,v);
 50         t[u].v=t[u*2].v+t[u*2+1].v;
 51     }
 52     ll query(int l,int r,int u,int L,int R){
 53         if(L<=l&&r<=R){
 54             return t[u].v;
 55         }
 56         int mid=(l+r)/2;
 57         ll ret=0;
 58         pd(u,l,r);
 59         if(L<=mid)ret=query(l,mid,u*2,L,R);
 60         if(mid<R)ret+=query(mid+1,r,u*2+1,L,R);
 61         return ret;
 62     }
 63 }
 64 namespace lct{
 65     struct node{
 66         int son[2],fa,v;
 67     }t[200001];
 68     bool ntrt(int u){
 69         return t[t[u].fa].son[0]==u||t[t[u].fa].son[1]==u;
 70     }
 71     bool lr(int u){
 72         return t[t[u].fa].son[1]==u;
 73     }
 74     void rotate(int u){
 75         int f=t[u].fa,ff=t[f].fa,ch=lr(u);
 76         if(ntrt(f))t[ff].son[lr(f)]=u;
 77         t[f].son[ch]=t[u].son[ch^1];
 78         t[t[f].son[ch]].fa=f;
 79         t[u].son[ch^1]=f;
 80         t[f].fa=u;
 81         t[u].fa=ff;
 82     }
 83     void splay(int u){
 84         //printf("in splay %d %d\n",u,t[u].fa);
 85         while(ntrt(u)){
 86             int f=t[u].fa;
 87             if(ntrt(f))rotate(lr(u)^lr(f)?f:u);
 88             rotate(u);
 89         }
 90     }
 91     int get(int u){
 92         while(t[u].son[0])u=t[u].son[0];
 93         return u;
 94     }
 95     void access(int u){
 96         for(int now=0;u;now=u,u=t[u].fa){
 97             //printf("%d %d\n",u,now);
 98             splay(u);
 99             if(t[u].son[1]){
100                 int x=get(t[u].son[1]);
101                 sgt::updata(1,n,1,in[x],out[x],1);
102             }
103             if(now){
104                 int x=get(now);
105                 sgt::updata(1,n,1,in[x],out[x],-1);
106             }
107             t[u].son[1]=now;
108         }
109     }
110 }
111 void add(int u,int v){
112     a[++tot].v=v;
113     a[tot].next=head[u];
114     head[u]=tot;
115 }
116 void dfs(int u,int fa,int dpt){
117     dep[u]=dpt;
118     siz[u]=1;
119     in[u]=++tim;
120     nmd[tim]=u;
121     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
122         int v=a[tmp].v;
123         if(v!=fa){
124             lct::t[v].fa=u;
125             dfs(v,u,dpt+1);
126             siz[u]+=siz[v];
127         }
128     }
129     out[u]=tim;
130 }
131 int main(){
132     memset(head,-1,sizeof(head));
133     scanf("%d",&n);
134     for(int i=1;i<n;i++){
135         scanf("%d%d",&u,&v);
136         u++,v++;
137         add(u,v);
138         add(v,u);
139     }
140     dfs(1,0,1);
141     sgt::build(1,n,1);
142     scanf("%d",&q);
143     for(int i=1;i<=q;i++){
144         scanf("%s%d",op,&x);
145         x++;
146         if(op[0]=='O')lct::access(x);
147         else printf("%.8lf\n",(double)sgt::query(1,n,1,in[x],out[x])/(double)(siz[x]));
148     }
149     return 0;
150 }
posted @ 2018-10-12 11:56  DCDCBigBig  阅读(179)  评论(0编辑  收藏  举报