您的位置:首页 > 其它

Bzoj2157 旅游

2017-03-16 11:09 274 查看
Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 1488  Solved: 670

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。

 

Source

 

树 LCT 模拟

 

喜闻乐见一上午调一道题

LCT转来转去没法维护边权(不换根的话可以),就把每个边当成一个点,存好权值,连到它的两个端点上。

剩下的就是裸题

那么为什么要调一上午呢?

  树上原本的点是不存权值的,所以它们保存的min和max默认是0,所以……

  ↑傻傻意识不到

/*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
const int INF=0x3f3f3f3f;
const int mxn=400010;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline int min(const int x,const int y){return x<y?x:y;}
inline int max(const int x,const int y){return x>y?x:y;}
struct node{
int ch[2],fa;
int val,smm,mi,mx;
bool rev,VR;
}t[mxn];
inline bool isroot(int &x){
return (t[t[x].fa].ch[0]!=x && t[t[x].fa].ch[1]!=x);
}
inline void Vrev(int x){
//    if(x && t[x].VR){
if(x){
//        printf("Vrev:%d\n",x);
//        int lc=t[x].ch[0],rc=t[x].ch[1];
//        t[lc].VR^=1;t[rc].VR^=1;
t[x].smm=-t[x].smm;
t[x].val=-t[x].val;
int r1=t[x].mi,r2=t[x].mx;
t[x].mi=-r2;t[x].mx=-r1;
t[x].VR^=1;
}
return;
}
int ed;
void pushup(int x){
int lc=t[x].ch[0],rc=t[x].ch[1];
t[x].mi=min(t[lc].mi,t[rc].mi);
t[x].mx=max(t[lc].mx,t[rc].mx);
if(x>ed) t[x].mi=min(t[x].mi,t[x].val);
if(x>ed) t[x].mx=max(t[x].mx,t[x].val);
t[x].smm=t[lc].smm+t[rc].smm+t[x].val;
return;
}
inline void PD(int x){
int lc=t[x].ch[0],rc=t[x].ch[1];
if(t[x].VR){
t[x].VR^=1;
if(lc)Vrev(lc);
if(rc)Vrev(rc);
}
if(t[x].rev){
t[lc].rev^=1;
t[rc].rev^=1;
swap(t[x].ch[0],t[x].ch[1]);
t[x].rev^=1;
}
return;
}
void rotate(int x){
int y=t[x].fa,z=t[y].fa,lc,rc;
if(t[y].ch[0]==x)lc=0;else lc=1;rc=lc^1;
if(!isroot(y)){t[z].ch[t[z].ch[1]==y]=x;}
t[x].fa=z;t[y].fa=x;
t[t[x].ch[rc]].fa=y;t[y].ch[lc]=t[x].ch[rc];
t[x].ch[rc]=y;
pushup(y);
return;
}
int st[mxn],top=0;
void Splay(int x){
st[top=1]=x;
for(int i=x;!isroot(i);i=t[i].fa)st[++top]=t[i].fa;
//    for(int i=x;t[i].fa;i=t[i].fa)st[++top]=t[i].fa;
while(top)PD(st[top--]);
while(!isroot(x)){
int y=t[x].fa,z=t[y].fa;
if(!isroot(y)){
if((t[y].ch[0]==x)^(t[z].ch[0]==y))rotate(x);
rotate(y);
}
rotate(x);
}
pushup(x);
return;
}
void access(int x){
for(int y=0;x;x=t[x].fa){
Splay(x);
t[x].ch[1]=y;
pushup(x);
y=x;
}
return;
}
void mkroot(int x){
access(x);Splay(x);
t[x].rev^=1;
return;
}
void link(int x,int y){mkroot(x);t[x].fa=y;return;}
void sov(int x,int y){
mkroot(x);
access(y);
Splay(y);
return;
}
int n;
int id[mxn];
int main(){
int i,j;
int u,v,w;char op[5];
n=read();
for(i=1;i<=n;i++){t[i].mi=INF;t[i].mx=-INF;}
t[0].mi=INF;t[0].mx=-INF;t[0].smm=t[0].val=0;//init
ed=n;
for(i=1;i<ed;i++){
u=read()+1;v=read()+1;w=read();
id[i]=++n;
t
.mi=t
.mx=t
.smm=t
.val=w;
link(u,n);link(v,n);
}
int m=read();
while(m--){
scanf("%s",op);
switch(op[0]){
case 'C':{
u=read();w=read();
u=id[u];
access(u);Splay(u);
t[u].val=w;
pushup(u);
break;
}
case 'S':{
u=read()+1;v=read()+1;
sov(u,v);
printf("%d\n",t[v].smm);
break;
}
case 'M':{
u=read()+1;v=read()+1;
sov(u,v);
if(op[1]=='A'){
printf("%d\n",t[v].mx);
}
else{
printf("%d\n",t[v].mi);
}
break;
}
case 'N':{
u=read()+1;v=read()+1;
sov(u,v);
Vrev(v);
break;
}
/*            case 'D':{
for(int i=1;i<=n;i++){
printf("#%d: val:%d smm:%d fa:%d lc:%d rc:%d\n",i,t[i].val,t[i].smm,t[i].fa,t[i].ch[0],t[i].ch[1]);
}
break;
}*/
}
}
return 0;
}
/*
6
0 1 3
1 2 7
2 3 11
3 4 24
4 5 53
20
N 1 2
SUM 0 5
*/

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: