题目大意:
给出一棵树,有四种操作:
1、连接两棵子树
2、断开树上的一条边,使其成为两棵子树(Ps:必须以x为跟,断开y的子树)
3、给x到y这个路径上的所有节点增加w的权值
4、询问从x到y的路径上点权最大的值
写这种代码量稍微长一点的我总是要手残。。。
第2个操作Ps中的内容我最开始没注意到,调了很久都WA,最后去网上找到标程才发现。
所以认真审题真的很重要,有人在考试中为了节约那么一点点时间不认真读题,殊不知这样可能会造成无法挽回的错误,这个一定要吸取教训。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 300000 + 10;
const int maxm = 1000000;
const int inf = 0x3f3f3f3f;
struct Edge
{
int pos;
int next;
}E[maxm];
int w[maxn],lazy[maxn],Max[maxn],head[maxn];
int ch[maxn][2],pre[maxn];
bool rev[maxn];
int n,m,NE;
void init()
{
freopen("hdu4010.in","r",stdin);
freopen("hdu4010.out","w",stdout);
}
void dfs(int u,int f)
{
for(int i = head[u];i != -1;i = E[i].next)
{
int v = E[i].pos;
if(v == f)continue;
dfs(v,u);
pre[v] = u;
}
}
void Inc(int x,int val)
{
if(x)
{
lazy[x] += val;
w[x] += val;
Max[x] += val;
}
}
void update(int x)
{
Max[x] = max(w[x],max(Max[ ch[x][0] ],Max[ ch[x][1] ]));
}
void pushdown(int x)
{
if(lazy[x])
{
Inc(ch[x][0],lazy[x]);
Inc(ch[x][1],lazy[x]);
lazy[x] = 0;
}
if(rev[x])
{
swap(ch[x][0],ch[x][1]);
rev[ ch[x][0] ] = !rev[ ch[x][0] ];
rev[ ch[x][1] ] = !rev[ ch[x][1] ];
rev[x] = false;
}
}
bool isroot(int x)
{
return ch[pre[x]][0] != x && ch[pre[x]][1] != x;
}
void push_down(int x)
{
if(!isroot(x))push_down(pre[x]);
pushdown(x);
}
void rotate(int x,int f)
{
int y = pre[x],z = pre[y];
ch[y][!f] = ch[x][f];
pre[ ch[x][f] ] = y;
pre[x] = pre[y];
if(ch[z][0] == y)ch[z][0] = x;
else if(ch[z][1] == y)ch[z][1] = x;
pre[y] = x;
ch[x][f] = y;
update(y);
}
void splay(int x)
{
push_down(x);
while(!isroot(x))
{
if(isroot(pre[x]))rotate(x,ch[pre[x]][0] == x);
else
{
int y = pre[x],z = pre[y];
int f = (ch[z][0] == y);
if(ch[y][f] == x)rotate(x,!f),rotate(x,f);
else rotate(y,f),rotate(x,f);
}
}
update(x);
}
void access(int u)
{
for(int v = 0;u;v = u,u = pre[u])
{
splay(u);
ch[u][1] = v;
update(u);
}
}
bool check(int a,int b)
{
int x = a,y = b;
access(y);
for(y = 0;x;y = x,x = pre[x])
{
splay(x);
if(!pre[x])break;
}
for(;ch[x][1];x = ch[x][1]);
return x == b;
}
void evert(int x)
{
access(x);
splay(x);
rev[x] = !rev[x];
}
void cut(int x,int y)
{
if(x == y || !check(x,y))
{
printf("-1\n");
return;
}
evert(x);
splay(y);
pre[ ch[y][0] ] = pre[y];
pre[y] = ch[y][0] = 0;
}
int query(int a,int b)
{
if(!check(a,b))return -1;
int x = a,y = b;
access(y);
for(y = 0;x;y = x,x = pre[x])
{
splay(x);
if(!pre[x])return max(w[x],max(Max[ ch[x][1] ],Max[y]));
ch[x][1] = y;
update(x);
}
return -1;
}
void modify(int x,int y,int add)
{
if(!check(x,y))
{
printf("-1\n");
return;
}
access(y);
for(y = 0;x;y = x,x = pre[x])
{
splay(x);
if(!pre[x])
{
w[x] += add;
Inc(y,add);
Inc(ch[x][1],add);
return;
}
ch[x][1] = y;
update(x);
}
}
void link(int x,int y)
{
if(check(x,y))
{
printf("-1\n");
return;
}
evert(x);
pre[x] = y;
}
void Init()
{
memset(E,0,sizeof(E));
memset(head,-1,sizeof(head));
memset(rev,false,sizeof(rev));
memset(ch,0,sizeof(ch));
memset(pre,0,sizeof(pre));
memset(Max,0,sizeof(Max));
memset(lazy,0,sizeof(lazy));
memset(w,0,sizeof(w));
w[0] = -inf;
NE = 0;
}
void insert(int u,int v)
{
E[NE].pos = v;
E[NE].next = head[u];head[u] = NE++;
}
void readdata()
{
while(~scanf("%d",&n))
{
Init();
for(int i = 1;i < n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
insert(u,v);
insert(v,u);
}
for(int i = 1;i <= n;i++)
{
scanf("%d",&w[i]);
Max[i] = w[i];
}
dfs(1,0);
scanf("%d",&m);
for(int i = 1;i <= m;i++)
{
int op,x,y;
scanf("%d",&op);
if(op == 1)scanf("%d%d",&x,&y),link(x,y);
if(op == 2)scanf("%d%d",&x,&y),cut(x,y);
if(op == 3)
{
int w;
scanf("%d%d%d",&w,&x,&y);
modify(x,y,w);
}
if(op == 4)scanf("%d%d",&x,&y),printf("%d\n",query(x,y));
}
printf("\n");
}
}
int main()
{
init();
readdata();
return 0;
}