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\n"); 120 } 121 else{ 122 ans=0; 123 printf("No\n"); 124 } 125 } 126 } 127 return 0; 128 }