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
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
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\n",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\n",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\n",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;
}

浙公网安备 33010602011771号