数据结构(并查集||树链剖分):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的主要内容,如果未能解决你的问题,请参考以下文章
luogu题解 P4092 [HEOI2016/TJOI2016]树树链剖分