Bzoj2157 旅游
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
30 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
32
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 */
- BZOJ[2157]旅游 树链剖分+线段树
- 【BZOJ 2157】旅游
- [BZOJ2157]旅游
- [bzoj2157][树链剖分]旅游
- BZOJ 2157: 旅游 树链剖分
- BZOJ 2157: 旅游
- [BZOJ2157]旅游
- [BZOJ2157] 旅游 边权树链剖分
- 【BZOJ2157】旅游,树链剖分练习
- BZOJ 2157 旅游(动态树)
- 【bzoj2157】旅游(树链剖分边权)
- 【BZOJ2157】旅游
- BZOJ 2157 旅游(树链剖分+线段树)
- 【bzoj2157】旅游 树链剖分+线段树
- 【树链剖分】【bzoj2157】: 旅游
- [BZOJ2157] 旅游 树链剖分
- [BZOJ2049]洞穴勘测[BZOJ2157]旅游Link-Cut Tree模板题
- 【BZOJ2157】旅游 裸树链剖分
- [动态树 LCT] BZOJ 2157 旅游
- 【BZOJ2157】旅游 树链剖分+线段树