hdu6858(杭电多校第八场) Discovery of Cycles

首先预处理出以每条边i作为左端点,在最短的区间内能形成环的最小右端点,标记为 Ri,如果不存在这样的右端点(即从当前到结尾所有边都不能组成环), 则让 Ri = m + 1。

用动态树来删边、加边和判环。尽量拓展右端点,直到发现环,然后就删掉左端点所在的边并移动左端点(有点像单调队列),不断重复这个过程就可以求解所有的 Ri 了。

对于每次询问的 l 和 r,如果 r >= R[ l ] ,则能形成环,否则不能形成环。

代码:

  1 #include<bits/stdc++.h>
  2 #define lc c[x][0]
  3 #define rc c[x][1]
  4 using namespace std;
  5 const int N=3e5+10;
  6 const int M=3e5+10;
  7 int f[N],c[N][2];
  8 int st[N];
  9 bool tag[N];
 10 int R[N];
 11 struct edge{
 12     int from,to;
 13 }e[M];
 14 void init(){
 15     memset(f,0,sizeof(f));
 16     memset(c,0,sizeof(c));
 17     memset(tag,0,sizeof(tag));
 18 }
 19 inline bool nroot(int x){
 20     return c[f[x]][0]==x||c[f[x]][1]==x;
 21 }
 22 inline void pushr(int x){
 23     int t=lc;
 24     lc=rc,rc=t;
 25     tag[x]^=1;
 26 }
 27 inline void pushdown(int x){
 28     if(tag[x]){
 29         if(lc) pushr(lc);
 30         if(rc) pushr(rc);
 31         tag[x]=0;
 32     }
 33 }
 34 void rotate(int x){
 35     int y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
 36     if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
 37     if(w)f[w]=y;f[y]=x;f[x]=z;
 38 }
 39 void splay(int x){
 40     int y=x,z=0;
 41     st[++z]=y;
 42     while(nroot(y)) st[++z]=y=f[y];
 43     while(z) pushdown(st[z--]);
 44     while(nroot(x)){
 45         y=f[x];z=f[y];
 46         if(nroot(y))
 47             rotate((c[y][0]==x)^(c[z][0]==y)?x:y);
 48         rotate(x);
 49     }
 50 }
 51 void access(int x){//访问
 52     for(int y=0;x;x=f[y=x])
 53         splay(x),rc=y;
 54 }
 55 void makeroot(int x){//换根
 56     access(x);splay(x);
 57     pushr(x);
 58 }
 59 int findroot(int x){//找根(在真实的树中的)
 60     access(x);splay(x);
 61     while(lc)pushdown(x),x=lc;
 62     splay(x);
 63     return x;
 64 }
 65 void split(int x,int y){//提取路径
 66     makeroot(x);
 67     access(y);splay(y);
 68 }
 69 inline void link(int x,int y){//连边
 70     f[x]=y;
 71 }
 72 void cut(int x,int y){//断边
 73     makeroot(x);
 74     if(findroot(y)==x&&f[y]==x&&!c[y][0]){
 75         f[y]=c[x][1]=0;
 76     }
 77 }
 78 int main()
 79 {
 80     int T;
 81     scanf("%d",&T);
 82     while(T--){
 83         init();
 84         int n,m,q;
 85         scanf("%d%d%d",&n,&m,&q);
 86         for(int i=1;i<=m;i++){
 87             scanf("%d%d",&e[i].from,&e[i].to);
 88         }
 89         int l=1,r=1;
 90         while(l<=m){
 91             while(r<=m){
 92                 int u=e[r].from,v=e[r].to;
 93                 makeroot(u);
 94                 if(findroot(v)==u){
 95                     break;
 96                 }
 97                 link(u,v);
 98                 r++;
 99             }
100             if(r==m+1){
101                 for(int i=l;i<=m;i++)
102                     R[i]=m+1;
103                 break;
104             }
105             R[l]=r;
106             cut(e[l].from,e[l].to);
107             l++;
108         }
109         int ans=0;
110         while(q--){
111             int x,y;
112             scanf("%d%d",&x,&y);
113             int k1=(x^ans)%m+1;
114             int k2=(y^ans)%m+1;
115             x=min(k1,k2);
116             y=max(k1,k2);
117             if(y>=R[x]){
118                 ans=1;
119                 printf("Yes
");
120             }
121             else{
122                 ans=0;
123                 printf("No
");
124             }
125         }
126     }
127     return 0;
128 }
原文地址:https://www.cnblogs.com/--HY--/p/13509423.html