某校开展了同学们喜闻乐见的阳光长跑活动。为了能“为祖国健康工作五十年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动。一时间操场上熙熙攘攘,摩肩接踵,盛况空前。
为了让同学们更好地监督自己,学校推行了刷卡机制。
学校中有n个地点,用1到n的整数表示,每个地点设有若干个刷卡机。
有以下三类事件:
1、修建了一条连接A地点和B地点的跑道。
2、A点的刷卡机台数变为了B。
3、进行了一次长跑。问一个同学从A出发,最后到达B最多可以刷卡多少次。具体的要求如下:
当同学到达一个地点时,他可以在这里的每一台刷卡机上都刷卡。但每台刷卡机只能刷卡一次,即使多次到达同一地点也不能多次刷卡。
为了安全起见,每条跑道都需要设定一个方向,这条跑道只能按照这个方向单向通行。最多的刷卡次数即为在任意设定跑道方向,按照任意路径从A地点到B地点能刷卡的最多次数。
用LCT维护双联通
代码丑:
#include
#include
using namespace std;
#define N 200000
#define fa(x) (a.find(fa[x]))
#define f(x) (a.find(x))
#define son(x) (ch[fa(x)][1]==x)
inline char tc(void){
static char fl[10000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,10000,stdin),A==B)?EOF:*A++;
}
inline int read(void){
int a=0;char c;while((c=tc())<'0'||c>'9');
while(c>='0'&&c<='9')a=a*10+c-'0',c=tc();return a;
}
struct cet{
int f[N+5];
inline void init(int n){for(int i=1;i<=n;++i)f[i]=i;}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void merge(int x,int y){f[find(x)]=find(y);}
}a,b;
int n,m,fa[N+5],ch[N+5][2],v[N+5],t[N+5],sum[N+5];
bool rev[N+5];
inline bool isroot(int x){return ch[fa(x)][1]!=x&&ch[fa(x)][0]!=x;}
inline void update(int x){sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+v[x];}
inline void push(int x){if(rev[x])rev[x]^=1,rev[ch[x][0]]^=1,rev[ch[x][1]]^=1,swap(ch[x][0],ch[x][1]);}
inline void rotate(int x){
int y=fa(x),z=fa(y),o=son(x);
if(!isroot(y))ch[z][son(y)]=x;
fa[x]=z,fa[y]=x;if(ch[x][!o])fa[ch[x][!o]]=y;
ch[y][o]=ch[x][!o];ch[x][!o]=y,
update(y),update(x);
}
inline void splay(int x){
static int st[N+5],top;
top=0,st[++top]=x;
for(int i=x;!isroot(i);i=fa(i))st[++top]=fa(i);
while(top)push(st[top--]);
for(;!isroot(x);rotate(x))if(!isroot(fa(x)))
if(son(x)^son(fa(x)))rotate(x);
else rotate(fa(x));
}
inline void access(int x){static int h;h=0;while(x)splay(x),ch[x][1]=h,h=x,update(x),x=fa(x);}
inline void rever(int x){access(x),splay(x),rev[x]^=1;}
inline void link(int x,int y){rever(x),fa[x]=y,splay(x);}
inline void cut(int x,int y){rever(x),access(y),splay(y);}
void dfs(int x,int y){
x=f(x),y=f(y);
a.merge(x,y);
if(x!=y)v[y]+=v[x],v[x]=0;
if(ch[x][0])dfs(ch[x][0],y);
if(ch[x][1])dfs(ch[x][1],y);
}
int main(void){
register int i,j,x,y,_x,_y,opt;
n=read(),m=read();
for(i=1;i<=n;++i)t[i]=v[i]=sum[i]=read();
a.init(n),b.init(n);
while(m--){
opt=read();
switch(opt){
case 1:{
x=read(),y=read();
if(f(x)==f(y))break;
if(b.find(f(x))!=b.find(f(y))){
link(f(x),f(y)),b.merge(f(x),f(y));
}else{
rever(f(x));access(f(y));
splay(f(y)),
dfs(f(y),f(y)),a.merge(f(x),f(y));
}
break;
}
case 2:{
x=read(),y=read();
rever(f(x)),sum[f(x)]+=y-t[x];
v[f(x)]+=y-t[x];
t[x]=y;
break;
}
case 3:{
x=read(),y=read();
if(b.find(x)!=b.find(y)){
puts("-1");
break;
}
rever(f(x));
access(f(y));
splay(f(y));
printf("%d\n",sum[f(y)]);
break;
}
}
}
return 0;
}