WISCO信息组NOIP模拟赛-部落冲突

传送门


 首先肯定考虑树剖,这里没有要求区间加,所以可以用树状数组维护,不会卡常的

这里是边权,可以转化为点权:让每条边连接的较深的节点的点权等于边权即可,然后计算的时候减去lca

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #define MAXN 300005
  6 #define LOG 20
  7 using namespace std;
  8 int read(){
  9     int x=0;char ch=getchar();
 10     while(ch<'0'||ch>'9'){ch=getchar();}
 11     while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
 12     return x;
 13 }
 14 int n,T;
 15 int a[MAXN],dat[MAXN];
 16 int dep[MAXN],size[MAXN],gs[MAXN],fa[20][MAXN];
 17 int top[MAXN],tree[MAXN],pre[MAXN],tot;
 18 int first[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt;
 19 int id[MAXN],tmp;
 20 
 21 void add(int x,int y){
 22     nxt[++cnt]=first[x];first[x]=cnt;to[cnt]=y;
 23     nxt[++cnt]=first[y];first[y]=cnt;to[cnt]=x;
 24 }
 25 int lca(int x,int y){
 26     if(dep[x]<dep[y]){
 27         swap(x,y);
 28     }
 29     for(int k=dep[x]-dep[y],p=0;k;k>>=1,p++){
 30         if(k&1){
 31             x=fa[p][x];
 32         }
 33     }
 34     if(x==y){
 35         return x;
 36     }
 37     for(int k=LOG-1;k>=0;k--){
 38         if(fa[k][x]!=fa[k][y]){
 39             x=fa[k][x],y=fa[k][y];
 40         }
 41     }
 42     return fa[0][x];
 43 }
 44 void change(int k,int x){
 45     while(k<=n){
 46         dat[k]+=x;
 47         k+=(k&-k);
 48     }
 49 }
 50 int query(int k){
 51     int ret=0;
 52     while(k>=1){
 53         ret+=dat[k];
 54         k-=(k&-k);
 55     }
 56     return ret;
 57 }
 58 void dfs1(int x){
 59     size[x]=1;
 60     for(int e=first[x];e;e=nxt[e]){
 61         int y=to[e];
 62         if(y==fa[0][x]){
 63             continue;
 64         }
 65         fa[0][y]=x;
 66         dep[y]=dep[x]+1;
 67         dfs1(y);
 68         size[x]+=size[y];
 69         if(size[y]>size[gs[x]]){
 70             gs[x]=y;
 71         }
 72     }
 73 }
 74 void dfs2(int x,int t){
 75     top[x]=t;
 76     tree[x]=(++tot);
 77     pre[tot]=x;
 78     if(!gs[x]){
 79         return;
 80     }
 81     dfs2(gs[x],t);
 82     for(int e=first[x];e;e=nxt[e]){
 83         int y=to[e];
 84         if(y==fa[0][x]||y==gs[x]){
 85             continue;
 86         }
 87         dfs2(y,y);
 88     }
 89 }
 90 int ask(int x,int y){
 91     int f1=top[x],f2=top[y];
 92     if(dep[f1]<dep[f2]){
 93         swap(x,y),swap(f1,f2);
 94     }
 95     int ret=-a[lca(x,y)];
 96     while(f1!=f2){
 97         ret+=query(tree[x])-query(tree[f1]-1);
 98         x=fa[0][f1]; f1=top[x];
 99         if(dep[f1]<dep[f2]){
100             swap(x,y),swap(f1,f2);
101         }    
102     }
103     if(dep[x]<dep[y]){
104         swap(x,y);
105     }
106     ret+=query(tree[x])-query(tree[y]-1);
107     return (ret<=0);
108 }
109 void init(){
110     n=read();T=read();
111     for(int i=1;i<n;i++){
112         int x=read(),y=read();
113         add(x,y);
114     }
115     dfs1(1);
116     dfs2(1,1);
117     for(int k=1;k<LOG;k++){
118         for(int i=1;i<=n;i++){
119             fa[k][i]=fa[k-1][fa[k-1][i]];
120         }
121     }
122 }
123 void solve(){
124     char ch[5];
125     while(T--){
126         scanf("%s",ch);
127         int x=read();
128         if('Q'==ch[0]){
129             int y=read();
130             if(ask(x,y)){
131                 printf("Yes\n");
132             }
133             else{
134                 printf("No\n");
135             }
136         }
137         else if('C'==ch[0]){
138             int y=read();
139             if(dep[x]<dep[y]){
140                 swap(x,y);
141             }
142             change(tree[x],1);
143             a[x]++;
144             id[++tmp]=x;
145         }
146         else{
147             x=id[x];
148             change(tree[x],-1);
149             a[x]--;
150         }
151     }
152 }
153 int main()
154 {
155     init();
156     solve();
157     return 0;
158 }
树剖AC

也可以是树上差分,用树状数组+dfs序,本质上是差不多的

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #define MAXN 300005
  6 #define LOG 20
  7 using namespace std;
  8 int read(){
  9     int x=0;char ch=getchar();
 10     while(ch<'0'||ch>'9'){ch=getchar();}
 11     while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
 12     return x;
 13 }
 14 int n,T;
 15 int first[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt;
 16 int pin[MAXN],pout[MAXN],tot;
 17 int dat[MAXN<<1];
 18 int fa[LOG][MAXN],dep[MAXN];
 19 int id[MAXN],tmp;
 20 void change(int k,int x){
 21     while(k<=(n<<1)){
 22         dat[k]+=x;
 23         k+=(k&-k);
 24     }
 25 }
 26 int query(int k){
 27     int ret=0;
 28     while(k>=1){
 29         ret+=dat[k];
 30         k-=(k&-k);
 31     }
 32     return ret;
 33 }
 34 void add(int x,int y){
 35     nxt[++cnt]=first[x];first[x]=cnt;to[cnt]=y;
 36     nxt[++cnt]=first[y];first[y]=cnt;to[cnt]=x;
 37 }
 38 int lca(int x,int y){
 39     if(dep[x]<dep[y]){
 40         swap(x,y);
 41     }
 42     for(int k=dep[x]-dep[y],p=0;k;k>>=1,p++){
 43         if(k&1){
 44             x=fa[p][x];
 45         }
 46     }
 47     if(x==y){
 48         return x;
 49     }
 50     for(int k=LOG-1;k>=0;k--){
 51         if(fa[k][x]!=fa[k][y]){
 52             x=fa[k][x],y=fa[k][y];
 53         }
 54     }
 55     return fa[0][x];
 56 }
 57 void dfs(int x){
 58     pin[x]=(++tot);
 59     for(int e=first[x];e;e=nxt[e]){
 60         int y=to[e];
 61         if(y==fa[0][x]){
 62             continue;
 63         }
 64         dep[y]=dep[x]+1;
 65         fa[0][y]=x;
 66         dfs(y);
 67     }
 68     pout[x]=(++tot);
 69 }
 70 int ask(int x,int y){
 71     int t=query(pin[x])+query(pin[y])-2*query(pin[lca(x,y)]);
 72     return (t<=0);
 73 }
 74 void init(){
 75     n=read(); T=read();
 76     for(int i=1;i<n;i++){
 77         int x=read(),y=read();
 78         add(x,y);
 79     }    
 80     dfs(1);
 81     for(int k=1;k<LOG;k++){
 82         for(int i=1;i<=n;i++){
 83             fa[k][i]=fa[k-1][fa[k-1][i]];
 84         }
 85     }
 86 }
 87 void solve(){
 88     char ch[5]={0};
 89     while(T--){
 90         scanf("%s",ch);
 91         int x=read();
 92         if('Q'==ch[0]){
 93             int y=read();
 94             if(ask(x,y)){
 95                 printf("Yes\n");
 96             }
 97             else{
 98                 printf("No\n");
 99             }
100         }
101         else if('C'==ch[0]){
102             int y=read();
103             if(dep[x]<dep[y]){
104                 swap(x,y);
105             }
106             change(pin[x],1);
107             change(pout[x]+1,-1);
108             id[++tmp]=x;
109         }
110         else{
111             x=id[x];
112             change(pin[x],-1);
113             change(pout[x]+1,1);
114         }
115     }
116 }
117 int main()
118 {
119 //    freopen("data.in","r",stdin);
120     init();
121     solve();
122     return 0;
123 }
树上差分AC

 

posted @ 2017-11-03 22:52  white_hat_hacker  阅读(169)  评论(0编辑  收藏  举报