数据结构(并查集||树链剖分):HEOI 2016 tree

Posted 既然选择了远方,便只顾风雨兼程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构(并查集||树链剖分):HEOI 2016 tree相关的知识,希望对你有一定的参考价值。

技术分享

技术分享

技术分享

【注意事项】


为了体现增强版,题目限制和数据范围有所增强:

时间限制:1.5s

内存限制:128MB

对于15% 的数据,1<=N,Q<=1000.

对于35% 的数据,1<=N,Q<=10000.

对于50% 的数据,1<=N,Q<=100000,且数据均为官方数据.

对于100% 的数据,1<=N,Q<=1000000.

请注意常数因子对于程序运行的影响。

  并查集很简单,并查集就是倒序处理,表示删除一个点的标记,删除后不会再加回来,删完后,合并当前点与其father的集合,根为father的原来的根,具体看代码……

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cstdio>
 5 using namespace std;
 6 const int N=1000010;
 7 int cnt,fir[N],to[N*2],nxt[N*2];
 8 void addedge(int a,int b){
 9     nxt[++cnt]=fir[a];
10     to[fir[a]=cnt]=b;
11 }
12 int fa[N],vis[N],pre[N];
13 int qr[N],tp[N],ans[N];
14 void DFS(int x){
15     for(int i=fir[x];i;i=nxt[i])
16         if(to[i]!=pre[x]){
17             pre[to[i]]=x;
18             DFS(to[i]);
19         }
20 }
21 void DFS(int x,int f){
22     fa[x]=f;
23     for(int i=fir[x];i;i=nxt[i])
24         if(to[i]!=pre[x]){
25             if(!vis[to[i]])DFS(to[i],f);
26             else DFS(to[i],to[i]);
27         }
28 }
29 int Find(int x){return fa[x]==x?x:fa[x]=Find(fa[x]);}
30 int n,Q;char op[5];
31 int main(){
32     freopen("tree++.in","r",stdin);
33     freopen("tree++.out","w",stdout);
34     int sz=32<<20;
35     char*p=(char*)malloc(sz)+sz;
36     __asm__("movl %0,%%esp\n"::"r"(p));
37     scanf("%d%d",&n,&Q);
38     for(int i=1,a,b;i<n;i++){
39         scanf("%d%d",&a,&b);
40         addedge(a,b);
41         addedge(b,a);
42     }DFS(1);
43     for(int i=1;i<=Q;i++){
44         scanf("%s%d",op,&qr[i]);
45         tp[i]=op[0]==Q?0:1;
46     }
47     vis[1]=1;
48     for(int i=1;i<=Q;i++)
49         if(tp[i])vis[qr[i]]+=1;
50     DFS(1,1);
51     for(int i=Q;i>=1;i--){
52         if(!tp[i])
53             ans[i]=Find(qr[i]);
54         else{
55             if(!--vis[qr[i]]){
56                 int x=qr[i];
57                 fa[x]=Find(pre[x]);
58             }
59         }
60     }
61     for(int i=1;i<=Q;i++)
62         if(!tp[i])printf("%d\n",ans[i]);
63     return 0;
64 }

  树链剖分很好想,但慢了些。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <ctime>
 6 using namespace std;
 7 const int N=1000010;
 8 int cnt,fir[N],nxt[N*2],to[N*2];
 9 void addedge(int a,int b){
10     nxt[++cnt]=fir[a];to[fir[a]=cnt]=b;
11     nxt[++cnt]=fir[b];to[fir[b]=cnt]=a;
12 }
13 int sz[N],son[N],fa[N],dep[N];
14 void DFS(int x){sz[x]=1;
15     for(int i=fir[x];i;i=nxt[i])
16         if(to[i]!=fa[x]){
17             dep[to[i]]=dep[fa[to[i]]=x]+1;
18             DFS(to[i]);sz[x]+=sz[to[i]];
19             if(sz[son[x]]<sz[to[i]])son[x]=to[i];
20         }
21 }
22 int tot,id[N],rid[N],top[N];
23 void DFS(int x,int tp){
24     top[rid[id[x]=++tot]=x]=tp;
25     if(son[x])DFS(son[x],tp);
26     for(int i=fir[x];i;i=nxt[i])
27         if(to[i]!=fa[x]&&to[i]!=son[x])
28             DFS(to[i],to[i]);
29 }
30 int sum[N*4],pos[N*4];
31 #define mid (l+r>>1)
32 void Push_up(int x){
33     sum[x]=sum[x<<1]+sum[x<<1|1];
34     if(sum[x]==0)pos[x]=0;
35     if(sum[x<<1|1])pos[x]=pos[x<<1|1];
36     else pos[x]=pos[x<<1];
37 }
38 void Update(int x,int l,int r,int g){
39     if(l==r){pos[x]=rid[l];sum[x]+=1;return;}
40     if(mid>=g)Update(x<<1,l,mid,g);
41     else Update(x<<1|1,mid+1,r,g);
42     Push_up(x);
43 }
44 
45 int Query(int x,int l,int r,int a,int b){
46     //if(!sum[x])return 0;
47     if(l>=a&&r<=b)return pos[x];int ret=0;
48     if(mid<b)ret=Query(x<<1|1,mid+1,r,a,b);
49     if(!ret&&mid>=a)ret=Query(x<<1,l,mid,a,b);
50     return ret;    
51 }
52 
53 int tag[N],n,Q,x;
54 int Solve(int x){
55     while(x){
56         int d=Query(1,1,n,id[top[x]],id[x]);
57         if(d)return d;x=fa[top[x]];
58     }
59     return 0;
60 }
61 char op[5],c;
62 void read(int &x){
63     x=0;while(c=getchar(),c>9||c<0);
64     while(x=x*10+(c^48),c=getchar(),c>=0&&c<=9);    
65 }    
66 int main(){
67     freopen("tree++.in","r",stdin);
68     freopen("tree++.out","w",stdout); 
69     read(n);read(Q);
70     int size = 32 << 20; // 256MB  
71     char *p = (char*)malloc(size) + size;  
72     __asm__("movl %0, %%esp\n" :: "r"(p));
73     for(int i=1,a,b;i<n;i++){
74         read(a);read(b);
75         addedge(a,b);
76     }
77     DFS(1);DFS(1,1);
78     Update(1,1,n,1);tag[1]=1;
79     while(Q--){
80         scanf("%s",op);read(x);
81         if(op[0]==C){
82             if(tag[x])continue;
83             Update(1,1,n,id[x]);
84             tag[x]=1;
85         }
86         else{
87             printf("%d\n",Solve(x));
88         }
89     }
90     //printf("%.2f\n",1.0*clock()/CLOCKS_PER_SEC);
91     return 0;
92 }

 

以上是关于数据结构(并查集||树链剖分):HEOI 2016 tree的主要内容,如果未能解决你的问题,请参考以下文章

hdu 5458 Stability(树链剖分+并查集)

luogu题解 P4092 [HEOI2016/TJOI2016]树树链剖分

[HDU3710] Battle Over Cities [树链剖分+线段树+并查集+kruskal+思维]

BZOJ 1969 树链剖分+Tarjan缩点

TJOI&HEOI2016Bzoj4551树

数据结构(树链剖分,线段树):SDOI 2016 游戏