BZOJ2157: 旅游

BZOJ2157: 旅游

Description

Ray 乐忠于旅游,这次他来到了T 城。

T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。

为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。

换句话说, T 城中只有N − 1 座桥。

Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。

于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。

有时,Ray 看待同一座桥的心情也会发生改变。

现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。

有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。

Input

输入的第一行包含一个整数N,表示T 城中的景点个数。景点编号为 0...N − 1。

接下来N − 1 行,每行三个整数u、v 和w,表示有一条u 到v,使 Ray 愉悦度增加w 的桥。

桥的编号为1...N − 1。|w| <= 1000。

输入的第N + 1 行包含一个整数M,表示Ray 的操作数目。

接下来有M 行,每行描述了一个操作,操作有如下五种形式:

C i w,表示Ray 对于经过第i 座桥的愉悦度变成了w。

N u v,表示Ray 对于经过景点u 到v 的路径上的每一座桥的愉悦度都变成原来的相反数。

SUM u v,表示询问从景点u 到v 所获得的总愉悦度。

MAX u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最大愉悦度。

MIN u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最小愉悦度。

测试数据保证,任意时刻,Ray 对于经过每一座桥的愉悦度的绝对值小于等于1000。

Output

对于每一个询问(操作S、MAX 和MIN),输出答案。

Sample Input

3
0 1 1
1 2 2
8
SUM 0 2
MAX 0 2
N 0 1
SUM 0 2
MIN 0 2
C 1 3
SUM 0 2
MAX 0 2

Sample Output

3
2
1
-1
5
3

HINT

一共有10 个数据,对于第i (1 <= i <= 10) 个数据, N = M = i * 2000。


题解Here!
一道很沙茶的树剖码农题。。。
基本操作就不讲了。。。
注意一些标记没有清空之类的细节就好了。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define DATA1(x) b[x].data1
#define DATA2(x) b[x].data2
#define DATA3(x) b[x].data3
#define SIGN(x) b[x].c
#define LSIDE(x) b[x].l
#define RSIDE(x) b[x].r
#define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
#define MAXN 100010
#define MAX 2147483647
using namespace std;
int n,m,c=1,d=1;
int head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],top[MAXN];
struct node1{
	int next,to,w;
}a[MAXN<<1];
struct node2{
	int data1,data2,data3,c;
	int l,r;
}b[MAXN<<2];
struct node3{
	int u,v,w;
}g[MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline int max(const int x,const int y){return x>y?x:y;}
inline int min(const int x,const int y){return x<y?x:y;}
inline void add(int u,int v,int w){
	a[c].to=v;a[c].w=w;
	a[c].next=head[u];
	head[u]=c++;
	a[c].to=u;a[c].w=w;
	a[c].next=head[v];
	head[v]=c++;
}
void dfs1(int rt){
	son[rt]=0;size[rt]=1;
	for(int i=head[rt];i;i=a[i].next){
		int will=a[i].to;
		if(!deep[will]){
			deep[will]=deep[rt]+1;
			fa[will]=rt;
			dfs1(will);
			size[rt]+=size[will];
			if(size[will]>size[son[rt]])son[rt]=will;
		}
	}
}
void dfs2(int rt,int f){
	id[rt]=d++;top[rt]=f;
	if(son[rt])dfs2(son[rt],f);
	for(int i=head[rt];i;i=a[i].next){
		int will=a[i].to;
		if(will!=fa[rt]&&will!=son[rt])
		dfs2(will,will);
	}
}
inline void pushup(int rt){
	DATA1(rt)=DATA1(LSON)+DATA1(RSON);
	DATA2(rt)=max(DATA2(LSON),DATA2(RSON));
	DATA3(rt)=min(DATA3(LSON),DATA3(RSON));
}
inline void pushdown(int rt){
	if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt))return;
	SIGN(LSON)^=SIGN(rt);
	DATA1(LSON)=-DATA1(LSON);DATA2(LSON)=-DATA2(LSON);DATA3(LSON)=-DATA3(LSON);
	swap(DATA2(LSON),DATA3(LSON));
	SIGN(RSON)^=SIGN(rt);
	DATA1(RSON)=-DATA1(RSON);DATA2(RSON)=-DATA2(RSON);DATA3(RSON)=-DATA3(RSON);
	swap(DATA2(RSON),DATA3(RSON));
	SIGN(rt)=0;
}
void buildtree(int l,int r,int rt){
	int mid;
	LSIDE(rt)=l;
	RSIDE(rt)=r;
	if(l==r){
		DATA1(rt)=DATA2(rt)=DATA3(rt)=0;
		return;
	}
	mid=l+r>>1;
	buildtree(l,mid,LSON);
	buildtree(mid+1,r,RSON);
	pushup(rt);
}
void update_change(int l,int r,int c,int rt){
	int mid;
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
		DATA1(rt)=DATA2(rt)=DATA3(rt)=c;
		return;
	}
	pushdown(rt);
	mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)update_change(l,r,c,LSON);
	if(mid<r)update_change(l,r,c,RSON);
	pushup(rt);
}
void update_null(int l,int r,int rt){
	int mid;
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
		SIGN(rt)^=1;
		DATA1(rt)=-DATA1(rt);DATA2(rt)=-DATA2(rt);DATA3(rt)=-DATA3(rt);
		swap(DATA2(rt),DATA3(rt));
		return;
	}
	pushdown(rt);
	mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)update_null(l,r,LSON);
	if(mid<r)update_null(l,r,RSON);
	pushup(rt);
}
int query_sum(int l,int r,int rt){
	int mid,ans=0;
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
	return DATA1(rt);
	pushdown(rt);
	mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)ans+=query_sum(l,r,LSON);
	if(mid<r)ans+=query_sum(l,r,RSON);
	return ans;
}
int query_max(int l,int r,int rt){
	int mid,ans=-MAX;
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
	return DATA2(rt);
	pushdown(rt);
	mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)ans=max(ans,query_max(l,r,LSON));
	if(mid<r)ans=max(ans,query_max(l,r,RSON));
	return ans;
}
int query_min(int l,int r,int rt){
	int mid,ans=MAX;
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
	return DATA3(rt);
	pushdown(rt);
	mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)ans=min(ans,query_min(l,r,LSON));
	if(mid<r)ans=min(ans,query_min(l,r,RSON));
	return ans;
}
void work1(int x,int y){
	while(top[x]!=top[y]){
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		update_null(id[top[x]],id[x],1);
		x=fa[top[x]];
	}
	if(deep[x]>deep[y])swap(x,y);
	update_null(id[x]+1,id[y],1);
	return;
}
void work2(int x,int y){
	int s=0;
	while(top[x]!=top[y]){
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		s+=query_sum(id[top[x]],id[x],1);
		x=fa[top[x]];
	}
	if(deep[x]>deep[y])swap(x,y);
	s+=query_sum(id[x]+1,id[y],1);
	printf("%d
",s);
	return;
}
void work3(int x,int y){
	int s=-MAX;
	while(top[x]!=top[y]){
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		s=max(s,query_max(id[top[x]],id[x],1));
		x=fa[top[x]];
	}
	if(deep[x]>deep[y])swap(x,y);
	s=max(s,query_max(id[x]+1,id[y],1));
	printf("%d
",s);
	return;
}
void work4(int x,int y){
	int s=MAX;
	while(top[x]!=top[y]){
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		s=min(s,query_min(id[top[x]],id[x],1));
		x=fa[top[x]];
	}
	if(deep[x]>deep[y])swap(x,y);
	s=min(s,query_min(id[x]+1,id[y],1));
	printf("%d
",s);
	return;
}
void work(){
	char ch[10];
	int x,y;
	m=read();
	while(m--){
		scanf("%s",ch);x=read()+1;y=read()+1;
		switch(ch[0]){
			case 'C':{
				x--;y--;
				update_change(id[g[x].v],id[g[x].v],y,1);
				break;
			}
			case 'N':work1(x,y);break;
			case 'S':work2(x,y);break;
			case 'M':{
				if(ch[1]=='A')work3(x,y);
				if(ch[1]=='I')work4(x,y);
				break;
			}
		}
	}
}
void init(){
	n=read();
	for(int i=1;i<n;i++){
		g[i].u=read()+1;g[i].v=read()+1;g[i].w=read();
		add(g[i].u,g[i].v,g[i].w);
	}
	deep[1]=1;
	dfs1(1);
	dfs2(1,1);
	buildtree(1,n,1);
	for(int i=1;i<n;i++){
		if(deep[g[i].u]>deep[g[i].v])swap(g[i].u,g[i].v);
		update_change(id[g[i].v],id[g[i].v],g[i].w,1);
	}
}
int main(){
	init();
	work();
	return 0;
}
原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9476118.html