【BZOJ3514】 Codechef MARCH14 GERALD07加强版
hentai。。。
原题:
N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。
对于100%的数据,1≤N、M、K≤200,000。
直接复制wulala的题解
wulala
葱娘说这是一个很巧妙的题。。
有一个比较猎奇的做法:首先把边依次加到图中,若当前这条边与图中的边形成了环,那么把这个环中最早加进来的边弹出去
并将每条边把哪条边弹了出去记录下来:ntr[i] = j,特别地,要是没有弹出边,ntr[i] = 0;
这个显然是可以用LCT来弄的对吧。
然后对于每个询问,我们的答案就是对l~r中ntr小于l的边求和,并用n减去这个值
正确性可以YY一下:
如果一条边的ntr >= l,那么显然他可以与从l ~ r中的边形成环,那么它对答案没有贡献
反之如果一条边的ntr < l那么它与从l ~ r中的边是不能形成环的,那么他对答案的贡献为-1
对于查询从l ~ r中有多少边的ntr小于l,我反正是用的函数式线段树
好妙啊
ntr。。。真是hentai,让我传承传承了hentai的po姐美好的意境吧
这题我写了一下午
T?WA我也认了T什么鬼啊
然后找rxz要来70M的数据。。。
突然想起来有些点是强制在线的,然后感觉就是我WA了
但是我把不强制在线的数据跑一下答案没错啊?
又从头到尾查一下,找不到毛病啊?
然后gdb,跟踪到第一个数据的时候……
一拍脑袋,发现last_ans没设初值。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 const int inf=(int)1e9; 8 int rd(){int z=0; char ch=getchar(); 9 while(ch<'0'||ch>'9') ch=getchar(); 10 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 11 return z; 12 } 13 struct edg{int x,y;}e[210000]; 14 int n,m,o,mk; 15 int fth[410000],chd[410000][2],v[410000],mnv[410000],rvs[410000]; 16 int stck[410000],tp=0; 17 int ntr[210000],c[210000]; 18 int w[8100000],cwd[8100000][2],rts[210000],ndc=0; 19 inline bool isrt(int x){ return (chd[fth[x]][0]!=x)&(chd[fth[x]][1]!=x);} 20 inline void pshu(int x){ mnv[x]=min(v[x],min(mnv[chd[x][0]],mnv[chd[x][1]]));} 21 inline void pshd(int x){ 22 if(!rvs[x]) return ; 23 rvs[chd[x][0]]^=1,rvs[chd[x][1]]^=1,rvs[x]=0; 24 swap(chd[x][0],chd[x][1]); 25 } 26 void rtt(int x){ 27 int y=fth[x],z=fth[fth[x]],l,r; 28 r=(chd[y][0]==x); l=r^1; 29 if(!isrt(y)) chd[z][chd[z][1]==y]=x; 30 fth[x]=z,fth[y]=x,fth[chd[x][r]]=y; 31 chd[y][l]=chd[x][r],chd[x][r]=y; 32 pshu(y),pshu(x); 33 } 34 void sply(int x){ 35 stck[tp=1]=x; 36 for(int i=x;!isrt(i);i=fth[i]) stck[++tp]=fth[i]; 37 while(tp) pshd(stck[tp--]); 38 while(!isrt(x)){ 39 if(!isrt(fth[x])) rtt((chd[fth[x]][0]==x)^(chd[fth[fth[x]]][0]==fth[x])?x:fth[x]); 40 rtt(x); 41 } 42 } 43 inline void accs(int x){ for(int i=0;x;sply(x),chd[x][1]=i,pshu(x),x=fth[i=x]);} 44 inline void qdrt(int x){ accs(x),sply(x),rvs[x]^=1;} 45 inline void ct(int x,int y){ qdrt(x),accs(y),sply(y),chd[y][0]=fth[x]=0;} 46 inline void lk(int x,int y){ qdrt(x),fth[x]=y,sply(x);} 47 inline int gtrt(int x){ while(fth[x]) x=fth[x]; return x;} 48 inline int sch(int x,int y){ qdrt(x),accs(y),sply(y); return mnv[y];} 49 void ist(int x){ 50 if(e[x].x==e[x].y){ ntr[x]=x; return ;} 51 if(gtrt(e[x].x)==gtrt(e[x].y)){ 52 ntr[x]=sch(e[x].x,e[x].y); 53 ct(n+ntr[x],e[ntr[x]].x),ct(n+ntr[x],e[ntr[x]].y); 54 mnv[n+ntr[x]]=inf; 55 } 56 mnv[n+x]=v[n+x]=x; 57 lk(n+x,e[x].x),lk(n+x,e[x].y); 58 } 59 /*int bnrsch(int x){ 60 int l=1,r=m,md; 61 while(l+1<r) md=(l+r)>>1,(c[md]>=x ? l : r)=md; 62 return c[md]==l ? l : r; 63 }*/ 64 int gtsgmttr(int l,int r){ 65 int x=++ndc,md=(l+r)>>1; 66 if(l!=r) cwd[x][0]=gtsgmttr(l,md),cwd[x][1]=gtsgmttr(md+1,r); 67 return x; 68 } 69 int mdf(int x,int l,int r,int y,int z){ 70 w[++ndc]=w[x],cwd[ndc][0]=cwd[x][0],cwd[ndc][1]=cwd[x][1],x=ndc; 71 if(l==r){ w[x]+=z; return x;} 72 int md=(l+r)>>1; 73 if(y<=md) cwd[x][0]=mdf(cwd[x][0],l,md,y,z); 74 else cwd[x][1]=mdf(cwd[x][1],md+1,r,y,z); 75 w[x]=w[cwd[x][0]]+w[cwd[x][1]]; 76 return x; 77 } 78 int qur(int x,int l,int r,int ql,int qr){ 79 if(l==ql && r==qr) return w[x]; 80 int md=(l+r)>>1; 81 if(ql<=md && qr>md) return qur(cwd[x][0],l,md,ql,md)+qur(cwd[x][1],md+1,r,md+1,qr); 82 else if(qr<=md) return qur(cwd[x][0],l,md,ql,qr); 83 else return qur(cwd[x][1],md+1,r,ql,qr); 84 } 85 int main(){//freopen("ddd.in","r",stdin); 86 //freopen("ddd.out","w",stdout); 87 int l,r,lst; 88 cin>>n>>m>>o>>mk; 89 fill(mnv,mnv+m+n+1,inf),fill(v,v+m+n+1,inf); 90 for(int i=1;i<=m;++i) e[i].x=rd(),e[i].y=rd(),ist(i); 91 /*for(int i=1;i<=m;++i) c[i]=ntr[i]; 92 sort(c+1,c+m+1); 93 for(int i=1;i<=m;++i) ntr[i]=bnrsch(ntr[i]);*/ 94 rts[0]=gtsgmttr(0,m); 95 for(int i=1;i<=m;++i) rts[i]=mdf(rts[i-1],0,m,ntr[i],1); 96 lst=0; 97 for(int i=1;i<=o;++i){ 98 l=rd()^(mk*lst),r=rd()^(mk*lst); 99 printf("%d\n",lst=n-qur(rts[r],0,m,0,l-1)+qur(rts[l-1],0,m,0,l-1)); 100 } 101 return 0; 102 }