hdu4010
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<stack>
using namespace std;
const int N=300005;
int n,q;
int u[N],v[N];
int fa[N],ch[N][2],w[N],rev[N],add[N],mx[N];
stack<int> s;
bool isroot(int u)
{
return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u;
}
void up(int u)
{
mx[u]=w[u];
if (ch[u][0]&&mx[ch[u][0]]>mx[u]) mx[u]=mx[ch[u][0]];
if (ch[u][1]&&mx[ch[u][1]]>mx[u]) mx[u]=mx[ch[u][1]];
}
void down(int u)
{
int l=ch[u][0],r=ch[u][1];
if (rev[u])
{
rev[u]^=1,rev[l]^=1,rev[r]^=1;
swap(ch[u][0],ch[u][1]);
}
if (add[u])
{
add[l]+=add[u],add[r]+=add[u];
mx[l]+=add[u],mx[r]+=add[u];
w[l]+=add[u],w[r]+=add[u];
add[u]=0;
}
}
void rot(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0;else l=1;r=l^1;
if (!isroot(y))
if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
fa[x]=z,fa[y]=x,fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
up(y);
}
void splay(int x)
{
int y=x,z;
while (!isroot(y)) s.push(y),y=fa[y];s.push(y);
while (!s.empty()) down(s.top()),s.pop();
while (!isroot(x))
{
y=fa[x],z=fa[y];
if (!isroot(y))
if (ch[y][0]==x^ch[z][0]==y) rot(x);else rot(y);
rot(x);
}
up(x);
}
void access(int x)
{
int t=0;
while (x)
{
splay(x);down(x);
ch[x][1]=t;up(x);
t=x,x=fa[x];
}
}
void to_rt(int x)
{
access(x);splay(x);rev[x]^=1;
}
void link(int u,int v)
{
to_rt(u);fa[u]=v;
}
int find(int u)
{
access(u);splay(u);
while (ch[u][0]) u=ch[u][0];
return u;
}
void Add()
{
int u,v;
scanf("%d%d",&u,&v);
int fu=find(u),fv=find(v);
if (fu==fv) {printf("-1\n");return;}
link(u,v);
}
void del()
{
int u,v;
scanf("%d%d",&u,&v);
int fu=find(u),fv=find(v);
if (fu!=fv||u==v) {printf("-1\n");return;}
to_rt(u),access(v),splay(v);
fa[ch[v][0]]=0,ch[v][0]=0;up(v);
}
void add_val()
{
int u,v,ww;
scanf("%d%d%d",&ww,&u,&v);
int fu=find(u),fv=find(v);
if (fu!=fv) {printf("-1\n");return;}
to_rt(u);access(v);splay(v);
add[v]+=ww;w[v]+=ww;mx[v]+=ww;//在做标记的时候,不能只给标记数组更新,答案数组,权值数组相关的都要更新
}
void find_mx()
{
int u,v,w;
scanf("%d%d",&u,&v);
int fu=find(u),fv=find(v);
if (fu!=fv) {printf("-1\n");return;}
to_rt(u),access(v),splay(v);
printf("%d\n",mx[v]);
}
void work()
{
memset(fa,0,sizeof(fa));
memset(ch,0,sizeof(ch));
memset(rev,0,sizeof(rev));
memset(add,0,sizeof(add));
memset(mx,0,sizeof(mx));
for (int i=1;i<n;i++) scanf("%d%d",&u[i],&v[i]);
for (int i=1;i<=n;i++) scanf("%d",&w[i]),mx[i]=w[i];
for (int i=1;i<n;i++) link(u[i],v[i]);
scanf("%d",&q);
int opt;
while (q--)
{
scanf("%d",&opt);
switch(opt)
{
case 1:Add();break;
case 2:del();break;
case 3:add_val();break;
case 4:find_mx();break;
}
}
printf("\n");
}
int main()
{
int T;
while (~scanf("%d",&n)) work();
return 0;
}
spoj Query on a tree
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.
We will ask you to perfrom some instructions of the following form:
- CHANGE i ti : change the cost of the i-th edge to ti
or - QUERY a b : ask for the maximum edge cost on the path from node a to node b
lct处理边权:化边为点,化边权为点权
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<stack>
using namespace std;
const int N=20005;
const int inf=0x3f3f3f3f;
struct aa
{
int u,v,c;
}bian[N];
stack<int> s;
int n,m;
int val[N],mx[N],fa[N],ch[N][2],rev[N];
void up(int x)
{
mx[x]=val[x];
if (ch[x][0]&&mx[ch[x][0]]>mx[x]) mx[x]=mx[ch[x][0]];
if (ch[x][1]&&mx[ch[x][1]]>mx[x]) mx[x]=mx[ch[x][1]];
}
void down(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]);
}
}
bool isroot(int u)
{
return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u;
}
void rot(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0;else l=1;r=l^1;
if (!isroot(y))
if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
up(y);
}
void splay(int x)
{
int y=x,z;
while (!isroot(y)) s.push(y),y=fa[y];s.push(y);
while (!s.empty()) down(s.top()),s.pop();
while (!isroot(x))
{
y=fa[x],z=fa[y];
if (!isroot(y))
if (ch[z][0]==y^ch[y][0]==x) rot(x);else rot(y);
rot(x);
}
up(x);
}
void access(int x)
{
int t=0;
while (x)
{
splay(x);down(x);
ch[x][1]=t;up(x);
t=x;x=fa[x];
}
}
void to_rt(int u)
{
access(u);splay(u);rev[u]^=1;
}
void link(int u,int v)
{
to_rt(u);fa[u]=v;
}
void work()
{
memset(fa,0,sizeof(fa));
memset(ch,0,sizeof(ch));
memset(rev,0,sizeof(rev));
memset(val,-inf,sizeof(val));
int u,v,c;
scanf("%d",&n);
for (int i=1;i<n;i++)
{
scanf("%d%d%d",&bian[i].u,&bian[i].v,&bian[i].c);
mx[i+n]=val[i+n]=bian[i].c;
link(i+n,bian[i].u);
link(i+n,bian[i].v);//以边做点
}
char ch[11];
do
{
scanf("%s",ch);
if (ch[0]=='D') break;
if (ch[0]=='C')
{
scanf("%d%d",&u,&c);
splay(u+n);val[u+n]=c;up(u+n);
}
else
{
scanf("%d%d",&u,&v);
to_rt(u);access(v);splay(v);
printf("%d\n",mx[v]);
}
}while(true);
}
int main()
{
int T;
scanf("%d",&T);
while (T--) work();
return 0;
}
lct版 bzoj1036 树的统计
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<stack>
using namespace std;
const int N=100005;
int n,q;
int u[N],v[N];
int fa[N],ch[N][2],rev[N],sum[N],mx[N],w[N];
bool isroot(int u)
{
return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u;
}
void up(int x)
{
int l=ch[x][0],r=ch[x][1];
mx[x]=sum[x]=w[x];
if (l)
{
mx[x]=max(mx[x],mx[l]);
sum[x]+=sum[l];
}
if (r)
{
mx[x]=max(mx[x],mx[r]);
sum[x]+=sum[r];
}
}
void down(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]);
}
}
void rot(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0;else l=1;r=l^1;
if (!isroot(y))
if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
fa[x]=z,fa[y]=x,fa[ch[x][r]]=y;
ch[y][l]=ch[x][r],ch[x][r]=y;
up(y);
}
stack<int> s;
void splay(int x)
{
int y=x,z;
while (!isroot(y)) s.push(y),y=fa[y];s.push(y);
while (!s.empty()) down(s.top()),s.pop();
while (!isroot(x))
{
y=fa[x],z=fa[y];
if (!isroot(y))
if (ch[y][0]==x^ch[z][0]==y) rot(x);else rot(y);
rot(x);
}
up(x);
}
void access(int x)
{
int t=0;
while (x)
{
splay(x);down(x);
ch[x][1]=t;up(x);
t=x,x=fa[x];
}
}
void to_rt(int u)
{
access(u),splay(u),rev[u]^=1;
}
void link(int u,int v)
{
to_rt(u);fa[u]=v;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<n;i++) scanf("%d%d",&u[i],&v[i]);
for (int i=1;i<=n;i++) scanf("%d",&w[i]),mx[i]=sum[i]=w[i];
for (int i=1;i<n;i++) link(u[i],v[i]);
scanf("%d",&q);
char ch[11];
int x,t;
while (q--)
{
scanf("%s",ch);
if (ch[1]=='H')
{
scanf("%d%d",&x,&t);
splay(x);w[x]=t;up(x);
}
else
if (ch[1]=='M')
{
scanf("%d%d",&x,&t);
to_rt(x),access(t),splay(t);
printf("%d\n",mx[t]);
}
else
{
scanf("%d%d",&x,&t);
to_rt(x),access(t),splay(t);
printf("%d\n",sum[t]);
}
}
return 0;
}
hdu3635 并查集
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=10005;
int n,q;
int fa[N],dep[N],size[N];
int find(int u)
{
if (u==fa[u]) return u;
int anc=find(fa[u]);
dep[u]+=dep[fa[u]];
fa[u]=anc;
return anc;
}
void work()
{
scanf("%d%d",&n,&q);
for (int i=1;i<=n;i++) fa[i]=i,dep[i]=0,size[i]=1;
char ch[2];
int u,v,fu,fv;
for (int i=1;i<=q;i++)
{
scanf("%s",ch);
if (ch[0]=='T')
{
scanf("%d%d",&u,&v);
fu=find(u),fv=find(v);
dep[fu]=1,fa[fu]=fv,size[fv]+=size[fu];
}
else
{
scanf("%d",&u);
v=find(u);
printf("%d %d %d\n",v,size[v],dep[u]);
}
}
}
int main()
{
int T;
scanf("%d",&T);
for (int i=1;i<=T;i++)
{
printf("Case %d:\n",i);
work();
}
return 0;
}