poj3237 树链剖分

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 10010
#define INF 0x7f7f7f7f
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
struct hh
{
	int v,w,next,num;
}edges[N<<1];
struct segtree
{
	int maxx,minn,delta;
}tree[N<<2];
int T,n,son[N],dep[N],fa[N],val[N],hash[N],from[N],size[N],top[N],point[N],a,b,tid[N],num[N],en,end;
char str[100];
int flag;
inline void init()
{
	memset(point,0xff,sizeof(point));
	en=-1;end=0;a=b=0;
}
inline void addedge(int u,int v,int w,int num)
{
	edges[++en].next=point[u];
	point[u]=en;
	edges[en].v=v;
	edges[en].w=w;
	edges[en].num=num;
	edges[++en].next=point[v];
	point[v]=en;
	edges[en].v=u;
	edges[en].w=w;
	edges[en].num=num;
}
inline void dfs(int x)
{
	size[x]=1;son[x]=0;
	for(int i=point[x];i!=-1;i=edges[i].next)
	if(edges[i].v!=fa[x])
	{
		fa[edges[i].v]=x;
		dep[edges[i].v]=dep[x]+1;
		from[edges[i].v]=i;
		dfs(edges[i].v);
		if(size[edges[i].v]>size[son[x]])son[x]=edges[i].v;
		size[x]+=size[edges[i].v];
	}
}
inline void make(int x,int anc)
{
	tid[x]=++end;val[end]=edges[from[x]].w;hash[edges[from[x]].num]=end;top[x]=anc;
	if(son[x]!=0)make(son[x],anc);
	for(int i=point[x];i!=-1;i=edges[i].next)
	if(edges[i].v!=fa[x]&&edges[i].v!=son[x])
	make(edges[i].v,edges[i].v);
}
inline void negative(int x)
{
	int tmp=tree[x].maxx;
	tree[x].maxx=-tree[x].minn;
	tree[x].minn=-tmp;
}
inline void push_up(int x)
{
	tree[x].maxx=MAX(tree[x<<1].maxx,tree[x<<1^1].maxx);
	tree[x].minn=MIN(tree[x<<1].minn,tree[x<<1^1].minn);
}
inline void push_down(int x)
{
	if(tree[x].delta)
	{
		tree[x<<1].delta^=1;
		tree[x<<1^1].delta^=1;
		negative(x<<1);
		negative(x<<1^1);
		tree[x].delta=0;
	}
}
inline void build(int x,int l,int r)
{
	if(l==r)
	{
		tree[x].maxx=tree[x].minn=val[l];
		tree[x].delta=0;
		return;
	}
	int mid=l+r>>1;
	build(x<<1,l,mid);
	build(x<<1^1,mid+1,r);
	push_up(x);
	tree[x].delta=0;
}
inline void update(int x,int l,int r,int left,int right,int delta)
{
	if(l>=left&&r<=right)
	{
		if(!flag)tree[x].maxx=tree[x].minn=delta;
		if(flag)
		{
			tree[x].delta^=1;
			negative(x);	
		}
		return;
	}
	int mid=l+r>>1;
	push_down(x);
	if(left<=mid)update(x<<1,l,mid,left,right,delta);
	if(right>mid)update(x<<1^1,mid+1,r,left,right,delta);
	push_up(x);
}
inline int query(int x,int l,int r,int left,int right)
{
	if(l>=left&&r<=right)return tree[x].maxx;
	int mid=l+r>>1,tmp1=-INF,tmp2=-INF;
	push_down(x);
	if(left<=mid)tmp1=query(x<<1,l,mid,left,right);
	if(right>mid)tmp2=query(x<<1^1,mid+1,r,left,right);
	push_up(x);
	return MAX(tmp1,tmp2);
}
inline void change(int x,int y)
{
	int f1=top[x],f2=top[y];
	while(f1!=f2)
	{
		if(dep[f1]<dep[f2]){swap(f1,f2);swap(x,y);}
		update(1,1,end,tid[f1],tid[x],0);
		x=fa[f1];f1=top[x];
	}
	if(x==y)return;
	if(dep[x]>dep[y])swap(x,y);
	update(1,1,end,tid[son[x]],tid[y],0);
}
inline int ask(int x,int y)
{
	if(x==y)return 0;
	int f1=top[x],f2=top[y],res=-INF,tmp;
	while(f1!=f2)
	{
		if(dep[f1]<dep[f2]){swap(x,y);swap(f1,f2);}
		tmp=query(1,1,end,tid[f1],tid[x]);
		res=MAX(res,tmp);
		x=fa[f1];f1=top[x];
	}
	if(x==y)return res;
	if(dep[x]>dep[y])swap(x,y);
	tmp=query(1,1,end,tid[son[x]],tid[y]);
	return MAX(res,tmp);
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		init();
		for(int i=1;i<n;i++)
		{
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			addedge(u,v,w,i);
		}
		dep[1]=0;
		dfs(1);
		make(1,1);
		build(1,1,end);
		while(1)
		{
			scanf(" %s",str);
			if(str[0]=='D')break;
			scanf("%d%d",&a,&b);
			if(str[0]=='C')flag=0,update(1,1,end,hash[a],hash[a],b);
			if(str[0]=='Q')printf("%d\n",ask(a,b));
			if(str[0]=='N')flag=1,change(a,b);
		}
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值