bool link(int x,int y){
mkrt(x);
if(fdrt(y)==x)return 0;
mkrt(y);//不加这一行就WA了
t[x].fa=y;
t[y].SIZ+=t[x].siz;
return 1;
}
与普通的LCT相比,这题的link似乎要多加上一句makeroot(x),不然全WA评测记录。但原模板对于其他题目都适用,不知道是这题特殊原因,还是其他题目没hack掉模板?
附第一组数据和代码。
P4219_1.in:
10 20
A 4 10
A 1 6
A 10 1
Q 4 10
A 9 8
A 7 9
Q 10 1
A 2 5
Q 9 8
Q 2 5
Q 4 10
Q 9 8
Q 2 5
A 8 3
Q 7 9
Q 2 5
A 5 7
Q 8 3
A 3 4
Q 7 9
P4219_1.out:
3
4
2
1
3
2
1
3
1
5
21
错误输出:
3
4
2
1
3
2
1
3
1
3
15
代码同第二篇hsfzLZH1题解思路
#include<bits/stdc++.h>
#define N 100010
using namespace std;
struct s{int siz,SIZ,fa,son[2];bool r;}t[N];
//siz:总子树节点数 SIZ:虚儿子子树节点数
int n,m,x,y;
char c;
int id(int x){return t[t[x].fa].son[1]^x?(t[t[x].fa].son[0]^x?-1:0):1;}
//结合get和isroot
void rev(int x){if(x)t[x].r^=1,swap(t[x].son[0],t[x].son[1]);}
void pd(int x){if(t[x].r)rev(t[x].son[0]),rev(t[x].son[1]),t[x].r=0;}
void pu(int x){t[x].siz=t[x].SIZ+t[t[x].son[0]].siz+t[t[x].son[1]].siz+1;}
void upd(int x){if(id(x)^-1)upd(t[x].fa);pd(x);}
void rot(int x){
int y=t[x].fa,z=t[y].fa,idx=id(x),idy=id(y);
if(t[x].son[idx^1])t[t[x].son[idx^1]].fa=y;t[y].son[idx]=t[x].son[idx^1];
t[y].fa=x;t[x].son[idx^1]=y;
t[x].fa=z;if(idy^-1)t[z].son[idy]=x;
pu(y),pu(x);
}
void splay(int x){
upd(x);
int idx,idy,y;
while((idx=id(x))^-1){if((idy=id(y=t[x].fa))^-1){rot(idx^idy?x:y);}rot(x);}
}
int lkrt(int x){//access
int w=0;
while(x){
splay(x);
t[x].SIZ+=t[t[x].son[1]].siz-t[w].siz;
t[x].son[1]=w;
pu(x);
x=t[w=x].fa;
}
return w;
}
void mkrt(int x){//makeroot
lkrt(x);
splay(x);
rev(x);
}
int fdrt(int x){//findroot
lkrt(x);
splay(x);
while(pd(x),t[x].son[0])x=t[x].son[0];
splay(x);
return x;
}
void spl(int x,int y){//split
mkrt(x);
lkrt(y);
splay(y);
}
bool link(int x,int y){
mkrt(x);
if(fdrt(y)==x)return 0;
mkrt(y);//关键一招
t[x].fa=y;
t[y].SIZ+=t[x].siz;
return 1;
}
bool cut(int x,int y){
mkrt(x);
if(fdrt(y)^x||t[y].fa^x||t[y].son[0])return 0;
t[y].fa=t[x].son[1]=0;
pu(x);
return 1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("\n%c%d%d",&c,&x,&y);
if(c=='A'){
link(x,y);
}else{
spl(x,y);
cut(x,y);
mkrt(x),mkrt(y);
printf("%lld\n",(long long)t[x].siz*t[y].siz);
link(x,y);
}
}
}