洛谷3767 膜法 带权并查集+分治

这么一道题折磨了不知道多久。。。

本来一直在撕烤可持久化,题解也没有看懂

思路:

跑出dfs序,则每条边的作用范围都是两段连续区间,放到线段树上就是2logn个区间

全都在线段树上挂好

然后分治,每次往下跑的时候把边加上,往下跑的时候把边删掉(所以不能路径压缩)

(某dalao写了按秩合并,但是没写也能过,题目不卡)

  1 #include <bits/stdc++.h>
  2 #define MAXN 500000
  3 #define mid (l+r>>1)
  4 using namespace std;
  5 int n,m,top,TIME,X,Y;
  6 int beg[MAXN],en[MAXN],ans[MAXN],fir[MAXN],nex[MAXN];
  7 int fa[MAXN], sz[MAXN], d[MAXN], st[MAXN];
  8 vector<int> O[MAXN],out[MAXN];
  9 struct qry
 10 {
 11     int u,v,cas;
 12 }q[MAXN];
 13 int getfa(int x){return x==fa[x]?x:getfa(fa[x]);}
 14 int getdep(int x){return x==fa[x]?0:(d[x]+getdep(fa[x]))%5;}
 15 bool com(int x,int y)
 16 {
 17     return (beg[x]<beg[y] || (beg[x]==beg[y] && en[x]<en[y]));
 18 }
 19 void dfs(int now)
 20 {
 21     beg[now]=++TIME;
 22     for(int i=fir[now];i;i=nex[i])
 23         dfs(i);
 24     en[now]=TIME;
 25 }
 26 void add(int now,int l,int r,int x,int y,int z)
 27 {
 28     if(l==x&&r==y)
 29     {
 30         O[now].push_back(z);
 31     //    printf("%d %d %d\n",z,x,y);
 32         return;
 33     }
 34     if(x<=mid)
 35         add(now<<1,l,mid,x,min(mid,y),z);
 36     if(y>mid)
 37         add(now<<1|1,mid+1,r,max(x,mid+1),y,z);
 38 }
 39 void work(int now,int l,int r,int x)
 40 {
 41     if(l==8 && r==8)
 42         int e=1;
 43     bool ok=1;
 44     for(int i=0;i<O[now].size();i++)
 45     {
 46         qry _q=q[O[now][i]];
 47         if(getfa(_q.u)==getfa(_q.v))
 48         {
 49             if((getdep(_q.v)-getdep(_q.u)+5)%5!=_q.cas)
 50             {
 51                 ok=0;
 52                 break;
 53             }
 54         }
 55         else
 56         {
 57             X=getfa(_q.u),Y=getfa(_q.v);
 58             fa[st[++top]=Y]=X,d[Y]=(_q.cas+getdep(_q.u)-getdep(_q.v)+5)%5;
 59         }
 60     }
 61     if(ok)
 62         if(l==r)
 63             ans[l]=1;
 64         else
 65         {
 66             work(now<<1,l,mid,top);
 67             work(now<<1|1,mid+1,r,top);
 68         }
 69     while(top>x)
 70         fa[st[top]]=st[top],d[st[top]]=0,top--;
 71 }
 72 int main()
 73 {
 74     scanf("%d%d",&n,&m);
 75     for(int i=1;i<=m;i++)
 76     {
 77         int tem;
 78         scanf("%d%d",&tem,&q[i].cas);
 79         nex[i]=fir[tem];fir[tem]=i;
 80         if(q[i].cas<=2)
 81             scanf("%d%d",&q[i].u,&q[i].v);
 82         else
 83             scanf("%d",&tem),out[tem].push_back(i);
 84     }
 85     dfs(0);
 86     for(int i=1;i<=m;i++)
 87     if(q[i].cas<=2)
 88     {
 89         sort(out[i].begin(),out[i].end(),com);
 90         for(int j=0;j<=out[i].size();j++)
 91         {
 92             int L=j?en[out[i][j-1]]+1:beg[i];
 93             int R=j<out[i].size()?beg[out[i][j]]-1:en[i];
 94             if(L<=R)
 95             {
 96                 add(1,1,m+1,L,R,i);
 97             }
 98         }
 99     }
100     for(int i=1;i<=n;i++)
101         fa[i]=i;
102     top=0;
103     work(1,1,m+1,0);
104     for(int i=1;i<=m;i++)
105         puts(ans[beg[i]]?"excited":"naive");
106     return 0;
107 }

 

posted @ 2017-05-16 15:06  汪立超  阅读(175)  评论(0编辑  收藏  举报