主席树+LCT
每次加边的时候判断一下是否成环
如果没有就加进去否则弹出环内比序号最小边
然后统计答案
#include
#include
#include
#include
#include
using namespace std;
char c;
inline void read(int &a)
{
a=0;do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
struct Node
{
int data;
Node *lc,*rc,*f,*min;
int Rev;
inline bool H(){return f->lc==this||f->rc==this;}
inline bool l(){return f->lc==this;}
}*empty;
inline void Begin()
{
empty=new Node;
empty->lc=empty->rc=empty->min=empty;
empty->data=1<<29;
}
inline Node*New_Node()
{
Node *tp=new Node;
tp->lc=tp->rc=empty;
tp->min=0;
tp->Rev=0;
tp->f=tp;
return tp;
}
Node Poi[200001];
struct S
{
int x,y;
}L[200001];
inline void updata(Node *a)
{a->min=(a->lc->min->datarc->min->data)?a->lc->min:a->rc->min;a->min=(a->min->data>a->data)?a:a->min;}
inline void LC(Node *a)
{
Node *ne;
if(a->f->H())
if(a->f->l())
a->f->f->lc=a,ne=a->f->f;
else
a->f->f->rc=a,ne=a->f->f;
else if(a->f->f!=a->f)
ne=a->f->f;
else
ne=a;
a->rc->f=a->f;
a->f->lc=a->rc;
a->rc=a->f;
a->f->f=a;
a->f=ne;
updata(a->rc),updata(a);
}
inline void RC(Node *a)
{
Node *ne;
if(a->f->H())
if(a->f->l())
a->f->f->lc=a,ne=a->f->f;
else
a->f->f->rc=a,ne=a->f->f;
else if(a->f->f!=a->f)
ne=a->f->f;
else
ne=a;
a->lc->f=a->f;
a->f->rc=a->lc;
a->lc=a->f;
a->f->f=a;
a->f=ne;
updata(a->lc),updata(a);
}
inline void pushdown(Node *a){Node *lc=a->lc;a->lc=a->rc,a->rc=lc;a->lc->Rev^=1,a->rc->Rev^=1,a->Rev^=1;}
inline void Turn(Node *a)
{a->l()?LC(a):RC(a);}
inline void Twi(Node *a)
{
if(a->f->f->Rev)pushdown(a->f->f);
if(a->f->Rev)pushdown(a->f);
if(a->Rev)pushdown(a);
a->f->l()==a->l()?Turn(a->f):Turn(a);Turn(a);
}
inline void Onc(Node *a)
{
if(a->f->Rev)pushdown(a->f);
if(a->Rev)pushdown(a);
Turn(a);
}
inline void Splay(Node *a)
{
while(a->H()&&a->f->H())Twi(a);
while(a->H())Onc(a);
}
inline void Access(Node *a)
{
Splay(a);
while(true)
{
Splay(a);
if(a->f==a)
return;
Splay(a->f);
if(a->f->Rev)pushdown(a->f);
a->f->rc=a;
}
}
inline void MakeRoot(Node *a)
{
Access(a);
a->lc->Rev^=1;
a->lc=empty;
}
inline int Cut(Node *a,Node *b)
{
MakeRoot(a);
Access(b);
Node *tp;
while(a->f!=b)
Onc(a);
tp=a->rc->min;
Node *t1=&Poi[L[tp->data].x],*t2=&Poi[L[tp->data].y];
MakeRoot(t1);Access(t2);
while(t1->f!=t2)
Onc(t1);
t2->lc=empty;
t1->f=t1;
return tp->data;
}
inline void Link(Node *a,Node *b,int data)
{
MakeRoot(a);
Access(b);
Node *c=New_Node();
a->f=c;
c->rc=a;
c->data=data;
c->f=b;
updata(c);
}
struct Seg
{
Seg *lc,*rc;
int l,r;
int data;
};
Seg *History[200001];
Seg*Build(int l,int r)
{
Seg *tp=new Seg;
tp->l=l,tp->r=r,tp->data=0;
tp->lc=NULL;tp->rc=NULL;
if(l^r)
tp->lc=Build(l,(l+r)>>1),
tp->rc=Build(((l+r)>>1)+1,r);
return tp;
}
Seg *Modify(Seg *old,int place)
{
Seg*tp=new Seg;
*tp=*old;
if(old->l^old->r)
{
if(place<=old->lc->r)
tp->lc=Modify(tp->lc,place);
else
tp->rc=Modify(tp->rc,place);
tp->data=tp->lc->data+tp->rc->data;
}
else
tp->data++;
return tp;
}
int Query(Seg *pl,int l)
{
if(!pl)return 0;
if(ll)return 0;
if(pl->r<=l)return pl->data;
return Query(pl->lc,l)+Query(pl->rc,l);
}
int F[200001];
int find(int x){return F[x]=(F[x]==x?x:find(F[x]));}
int Union(int x,int y){F[find(x)]=find(y);}
int main()
{
int n,m,k,type,i,j;
read(n);
Begin();
Node *t=New_Node();
for(i=1;i<=n;i++)
F[i]=i,Poi[i]=*t,Poi[i].min=&Poi[i],
Poi[i].f=&Poi[i],
Poi[i].data=1<<28;
read(m);
read(k);
read(type);
int tp;
History[0]=Build(0,200002);
for(i=1;i<=m;i++)
{
tp=0;
read(L[i].x),read(L[i].y);
if(find(L[i].x)^find(L[i].y))
{
Union(L[i].x,L[i].y);
Link(&Poi[L[i].x],&Poi[L[i].y],i);
}
else if(L[i].x!=L[i].y)
{
tp=Cut(&Poi[L[i].x],&Poi[L[i].y]);
Link(&Poi[L[i].x],&Poi[L[i].y],i);
}
else tp=200002;
History[i]=Modify(History[i-1],tp);
}
int l,r,lastans=0;
for(i=1;i<=k;i++)
{
read(l),read(r);
if(type)
l^=lastans,r^=lastans;
if(l>r)swap(l,r);
int Pop=Query(History[r],l-1)-Query(History[l-1],l-1);
printf("%d\n",lastans=(n-Pop));
}
return 0;
}