poj 3237

题意:给一颗树,边上有权有三种操作

Q u,v  u->v路径上权的最大值

C u,v  输入时的第u条边权值修改为v

N u,v u->v路径上边的权值*-1

 按照轻重边剖分,取反加个标记就好,记录最大值最小值,取反的时候反过来,再*-1,完成取反操作

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lc rt<<1
#define rc rt<<1|1
using namespace std;
const int maxn=1e4+5;
const int INF=1e9;
struct Node{int l,r,mx,mi;bool mark;}tr[maxn*4];
struct edge{int to,nxt,v;}e[maxn*3];
int fa[maxn],dep[maxn],son[maxn],siz[maxn],top[maxn];
int p[maxn],cnt,node,val[maxn],fp[maxn],head[maxn];
void addedge(int u,int v,int w){
	cnt++;e[cnt].to=v;e[cnt].nxt=head[u];
	e[cnt].v=w;head[u]=cnt;
}

void dfs1(int u){
	siz[u]=1;son[u]=0;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==fa[u])continue;
		fa[v]=u;dep[v]=dep[u]+1;val[v]=e[i].v;
		dfs1(v);
		siz[u]+=siz[v];
		if(siz[v]>siz[son[u]])son[u]=v;
	}
}
void dfs2(int u,int sp){
	p[u]=++node;top[u]=sp;fp[node]=u;
	if(son[u])dfs2(son[u],top[u]);
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v!=fa[u]&&v!=son[u])dfs2(v,v);
	}
}
inline void pushup(int rt){
	tr[rt].mx=max(tr[lc].mx,tr[rc].mx);
	tr[rt].mi=min(tr[lc].mi,tr[rc].mi);
}
inline void pushdown(int rt){
	if(tr[rt].mark){
		swap(tr[lc].mi,tr[lc].mx);tr[lc].mi*=-1;
		swap(tr[rc].mi,tr[rc].mx);tr[rc].mi*=-1;
		tr[lc].mx*=-1;tr[rc].mx*=-1;
		tr[lc].mark^=1;tr[rc].mark^=1;
		tr[rt].mark^=1;
	}
}

void build(int rt,int l,int r){
	tr[rt].l=l;tr[rt].r=r;tr[rt].mark=false;
	if(l==r){
		tr[rt].mi=tr[rt].mx=val[fp[l]];
	}
	else{
		int m=(l+r)>>1;
		build(lc,l,m);build(rc,m+1,r);
		pushup(rt);
	}
}
void update(int rt,int pp,int v){
	int l=tr[rt].l,r=tr[rt].r;
	if(l==r)tr[rt].mx=tr[rt].mi=v;
	else{
		pushdown(rt);
		int m=(l+r)>>1;
		if(pp<=m)update(lc,pp,v);
		else update(rc,pp,v);
		pushup(rt);
	}
}
void anti(int rt,int a,int b){
	int l=tr[rt].l,r=tr[rt].r;
	if(l==a&&b==r){
		tr[rt].mark^=1;swap(tr[rt].mx,tr[rt].mi);
		tr[rt].mx*=-1;tr[rt].mi*=-1;
	}
	else{
		pushdown(rt);
		int m=(l+r)>>1;
		if(b<=m) anti(lc,a,b);
		else if(m<a)anti(rc,a,b);
		else anti(lc,a,m),anti(rc,m+1,b);
		pushup(rt);
	}
}
int query(int rt,int a,int b){
	int l=tr[rt].l,r=tr[rt].r;
	if(l==a&&b==r)return tr[rt].mx;
	else{
		pushdown(rt);
		int m=(l+r)>>1;
		if(b<=m)return query(lc,a,b);
		else if(m<a)return query(rc,a,b);
		else return max(query(lc,a,m),query(rc,m+1,b));
	}
}
void change(int u,int v){
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		anti(1,p[top[u]],p[u]);
		u=fa[top[u]];
	}
	if(u==v)return ;
	if(dep[u]>dep[v])swap(u,v);
	anti(1,p[son[u]],p[v]);
}
int ask(int u,int v){
	int ans=-INF;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		ans=max(ans,query(1,p[top[u]],p[u]));
		u=fa[top[u]];
	}
	if(u==v)return ans;
	if(dep[u]>dep[v])swap(u,v);
	return max(ans,query(1,p[son[u]],p[v]));
}
int ee[maxn][2],u,v,w;
int main(){
	int t,n;scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		cnt=node=0;memset(head,0,sizeof(head));
		for(int i=1;i<n;i++){
			scanf("%d%d%d",&ee[i][0],&ee[i][1],&w);
			addedge(ee[i][0],ee[i][1],w);
			addedge(ee[i][1],ee[i][0],w);
		}
		dfs1(1);dfs2(1,1);
		build(1,1,n);
		char op[10];
		for(int i=1;i<n;i++)if(dep[ee[i][0]]>dep[ee[i][1]])swap(ee[i][0],ee[i][1]);
		while(true){
			scanf("%s",op);
			if(op[0]=='D')break;
			scanf("%d%d",&u,&v);
			if(op[0]=='C'){
				u=ee[u][1];
				update(1,p[u],v);
			}
			else if(op[0]=='Q')printf("%d\n",ask(u,v));
			else change(u,v);
		}
	}
	return 0;
}

 

posted @ 2016-10-22 12:00  N维解析几何  阅读(210)  评论(0编辑  收藏  举报