题解:
每一次加入一条边,记录一下弹出了那一条边
然后用lct维护即可
计算出来后,再用主席树做l-r的值
代码:
#include<bits/stdc++.h> typedef long long ll; const int N=400005; using namespace std; int type,n,m,Q,lastans,top,l,r,tot,sz,s[N],st[N],root[N]; int c[N][2],fa[N],val[N],mn[N],sum[N*10],ls[N*10],rs[N*10],rev[N]; struct edge{int u,v;}e[N]; int isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} void update(int x) { int l=c[x][0],r=c[x][1]; mn[x]=x; if (val[mn[l]]<val[mn[x]])mn[x]=mn[l]; if (val[mn[r]]<val[mn[x]])mn[x]=mn[r]; } void pushdown(int x) { int l=c[x][0],r=c[x][1]; if (rev[x]) { rev[x]^=1;rev[l]^=1;rev[r]^=1; swap(c[x][0],c[x][1]); } } void rotate(int x) { int y=fa[x],z=fa[y],l,r; if (c[y][0]==x)l=0;else l=1;r=l^1; if (!isroot(y)) { if(c[z][0]==y)c[z][0]=x; else c[z][1]=x; } fa[y]=x;fa[x]=z;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; update(y);update(x); } void down(int x){if (!isroot(x))down(fa[x]);pushdown(x);} void splay(int x) { down(x); for (int y=fa[x];!isroot(x);rotate(x),y=fa[x]) if (!isroot(y))rotate((c[y][0]==x)==(c[fa[y]][0]==y)?y:x); } void access(int x){for (int t=0;x;t=x,x=fa[x])splay(x),c[x][1]=t,update(x);} void makeroot(int x){access(x);splay(x);rev[x]^=1;} void link(int x,int y){makeroot(x);fa[x]=y;} void cut(int x,int y){makeroot(x);access(y);splay(y);c[y][0]=fa[x]=0;} int find(int x){access(x);splay(x);while (c[x][0])x=c[x][0];return x;} int query(int x,int y){makeroot(x);access(y);splay(y);return mn[y];} void insert(int l,int r,int x,int &y,int val) { y=++sz; sum[y]=sum[x]+1; if(l==r)return; ls[y]=ls[x];rs[y]=rs[x]; int mid=(l+r)/2; if (val<=mid)insert(l,mid,ls[x],ls[y],val); else insert(mid+1,r,rs[x],rs[y],val); } int query(int l,int r,int x,int y,int val) { if (r==val)return sum[y]-sum[x]; int mid=(l+r)/2; if (val<=mid)return query(l,mid,ls[x],ls[y],val); return sum[ls[y]]-sum[ls[x]]+query(mid+1,r,rs[x],rs[y],val); } int main() { scanf("%d%d%d%d",&n,&m,&Q,&type); val[0]=1e9; for (int i=1;i<=n;i++)mn[i]=i,val[i]=1e9; for (int i=1;i<=m;i++)scanf("%d%d",&e[i].u,&e[i].v); tot=n; for (int i=1;i<=m;i++) { int u=e[i].u,v=e[i].v; if (u==v){st[i]=i;continue;} if (find(u)==find(v)) { int t=query(u,v),x=val[t]; st[i]=x; cut(e[x].u,t);cut(e[x].v,t); } tot++; mn[tot]=tot;val[tot]=i; link(u,tot);link(v,tot); } for (int i=1;i<=m;i++)insert(0,m,root[i-1],root[i],st[i]); while (Q--) { scanf("%d%d",&l,&r); if (type)l^=lastans,r^=lastans; lastans=n-query(0,m,root[l-1],root[r],l-1); printf("%d ",lastans); } return 0; }