分析:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<assert.h>
#define SF scanf
#define PF printf
#define MAXN 200010
#define MOD 1000000009
using namespace std;
typedef long long ll;
struct node *NIL;
struct node{
node *ch[2],*fa;
int val,siz;
bool Dir(){
return this==fa->ch[1];
}
void setchild(node *x,int d){
ch[d]=x;
if(x!=NIL)
x->fa=this;
}
void pushup(){
siz=ch[0]->siz+ch[1]->siz+1;
}
}tree[MAXN*2];
int fax[MAXN];
node *lc[MAXN],*rc[MAXN];
node * Newnode(node *x,int val){
x->ch[0]=x->ch[1]=x->fa=NIL;
x->val=val;
x->siz=1;
return x;
}
void Rotate(node *x){
node *y=x->fa;
int d=x->Dir();
if(y->fa==NIL)
x->fa=NIL;
else
y->fa->setchild(x,y->Dir());
y->setchild(x->ch[!d],d);
x->setchild(y,!d);
y->pushup();
}
void Splay(node *x,node *rt){
while(x->fa!=rt){
node *y=x->fa;
if(y->fa==rt){
Rotate(x);
break;
}
if(x->Dir()==y->Dir())
Rotate(y);
else
Rotate(x);
Rotate(x);
}
x->pushup();
}
node *find_nxt(node *x,int d){
while(x->ch[d]!=NIL)
x=x->ch[d];
return x;
}
int check(int a,int b){
Splay(lc[a],NIL);
node *rta=find_nxt(lc[a],0);
Splay(rta,NIL);
Splay(lc[b],NIL);
node *rtb=find_nxt(lc[b],0);
Splay(rtb,NIL);
if(rta!=rtb)
return 0;
Splay(lc[a],NIL);
int siz1=lc[a]->ch[0]->siz;
Splay(rc[a],NIL);
int siz2=rc[a]->ch[0]->siz;
Splay(lc[b],NIL);
int siz=lc[b]->ch[0]->siz;
if(siz1<siz&&siz<siz2)
return 1;
if(fax[rta->val]!=0){
node *x=lc[fax[rta->val]];
Splay(x,NIL);
int sizx=x->ch[0]->siz;
if(siz1<=sizx&&sizx<=siz2)
return 1;
}
return 0;
}
void cut(int x){
node *a=lc[x];
node *b=rc[x];
Splay(a,NIL);
if(a->ch[0]==NIL){
fax[x]=0;
return ;
}
node *rt=find_nxt(a,0);
Splay(rt,NIL);
if(fax[rt->val]==0||check(x,fax[rt->val])==0){
Splay(rt,NIL);
Splay(a,rt);
Splay(b,a);
node *t=find_nxt(b->ch[1],0);
Splay(t,b);
rt->setchild(t,1);
t->setchild(a->ch[0],0);
a->fa=NIL;
a->ch[0]=NIL;
b->ch[1]=NIL;
t->pushup();
rt->pushup();
b->pushup();
a->pushup();//cut a from x
}
else{
node *c=lc[fax[rt->val]];
fax[rt->val]=0;
assert(rt->ch[0]==NIL);
Splay(rt,NIL);
Splay(a,rt);
Splay(b,a);
node *t=find_nxt(b->ch[1],0);
Splay(t,b);
rt->setchild(t,1);
t->setchild(a->ch[0],0);
a->fa=NIL;
a->ch[0]=NIL;
b->ch[1]=NIL;
t->pushup();
rt->pushup();
b->pushup();
a->pushup();//cut a from x
//PF("{%d %d}\n",a->ch[0]-tree,a->ch[1]-tree);
Splay(c,NIL);
node *d=find_nxt(c->ch[1],0);
Splay(d,c);
d->setchild(rt,0);
d->pushup();
c->pushup();
}
}
void link(int a,int b){
Splay(lc[a],NIL);
assert(lc[a]->ch[0]==NIL);
if(check(a,b)||a==b){//we can reach a from b
fax[a]=b;
}
else{
Splay(lc[a],NIL);
node *c=lc[b];
Splay(c,NIL);
node *d=find_nxt(c->ch[1],0);
Splay(d,c);
d->setchild(lc[a],0);
d->pushup();
c->pushup();
}
}
int n,m;
int main(){
freopen("repeater.in","r",stdin);
freopen("repeater.out","w",stdout);
int tag,a,b;
NIL=&tree[0];
NIL->ch[0]=NIL->ch[1]=NIL->fa=NIL;
SF("%d%d",&n,&m);
for(int i=1;i<=n;i++){
lc[i]=Newnode(&tree[i],i);
rc[i]=Newnode(&tree[i+n],i);
lc[i]->setchild(rc[i],1);
}
ll ans=0;
int cnt=0;
for(int i=1;i<=m;i++){
//PF("[now,begin %d]:\n",i);
SF("%d%d%d",&tag,&a,&b);
if(tag==1){
cut(a);
if(b!=0)
link(a,b);
}
else{
//PF("{%d}\n",check(b,a));
ans=(ans*2ll+check(b,a))%MOD;
}
/*for(int i=1;i<=n;i++){
PF("fa:(%d)",fax[i]);
PF("<%d,(%d),%d> | <%d,(%d),%d>\n",lc[i]->ch[0]-tree,lc[i]-tree,lc[i]->ch[1]-tree,rc[i]->ch[0]-tree,rc[i]-tree,rc[i]->ch[1]-tree);
}*/
}
PF("%lld",ans);
}