【BZOJ2157】旅游 LCT
模板T,SB的DMoon。。其实样例也是中国好样例。。。一开始不会复制,yangyang:找到“sample input”按住shift,按page down。。。。
1 #include <iostream> 2 #include <cstdio> 3 #define inf 0x7fffffff 4 #define N 20010 5 #define M 20010 6 using namespace std; 7 int n,m; 8 struct node *null; 9 struct node 10 { 11 node *fa,*ch[2]; 12 //node(int x,int flag); 13 int maxn,minn,data,sum; 14 bool rev,rev_data,ie; 15 bool chr() {return this==fa->ch[1];} 16 bool isrt() {return this!=fa->ch[1] && this !=fa->ch[0];} 17 void setc(node *x,int t) {this->ch[t]=x; x->fa=this;} 18 void push_up(); 19 void push_down(); 20 }pool[N+M],*pt=pool,*e[M],*p[N]; 21 void node::push_up() 22 { 23 if (this==null) return; 24 sum=ch[1]->sum+ch[0]->sum+data*ie; 25 maxn=max(ch[1]->maxn,ch[0]->maxn); if (ie) maxn=max(maxn,data); 26 minn=min(ch[1]->minn,ch[0]->minn); if (ie) minn=min(minn,data); 27 } 28 void node::push_down() 29 { 30 if (this==null) return; 31 if (!isrt()) fa->push_down(); 32 if (rev) 33 { 34 if (ch[0]!=null) ch[0]->rev^=1; 35 if (ch[1]!=null) ch[1]->rev^=1; 36 swap(ch[0],ch[1]); 37 rev=0; 38 } 39 if (rev_data) 40 { 41 if (ch[0]!=null) 42 { 43 int k=ch[0]->maxn; 44 ch[0]->rev_data^=1; 45 ch[0]->data=-ch[0]->data; 46 ch[0]->sum=-ch[0]->sum; 47 ch[0]->maxn=-ch[0]->minn; 48 ch[0]->minn=-k; 49 } 50 if (ch[1]!=null) 51 { 52 int k=ch[1]->maxn; 53 ch[1]->rev_data^=1; 54 ch[1]->sum=-ch[1]->sum; 55 ch[1]->maxn=-ch[1]->minn; 56 ch[1]->minn=-k; 57 ch[1]->data=-ch[1]->data; 58 } 59 // swap(ch[0],ch[1]);// 注意!!! 60 rev_data=0; 61 } 62 } 63 namespace LCT 64 { 65 node *NewNode(int x,int flag) 66 { 67 node *r=pt++; 68 r->fa=r->ch[0]=r->ch[1]=null; 69 r->data=r->sum=x; r->ie=flag; 70 if (flag) r->maxn=r->minn=x; 71 else r->maxn=-inf,r->minn=inf; 72 r->rev=r->rev_data=0; 73 return r; 74 } 75 void rotate(node *x) 76 { 77 node *r=x->fa; 78 if (r==null || x==null) return; 79 x->push_down(); r->push_down(); 80 bool t=x->chr(); 81 if (r->isrt()) x->fa=r->fa; // !!!在这里坑了好几次了 82 else r->fa->setc(x,r->chr()); 83 r->setc(x->ch[t^1],t); 84 x->setc(r,!t); 85 r->push_up(); x->push_up(); 86 } 87 void Splay(node *x) 88 { 89 //if (x==null) return; 90 x->push_down(); 91 for (;!x->isrt();rotate(x)) 92 if (!x->fa->isrt()) 93 if (x->chr()==x->fa->chr()) rotate(x->fa); 94 else rotate(x); 95 x->push_up(); 96 } 97 void Access(node *x) 98 { 99 node *r=null; 100 for (;x!=null;r=x,x=x->fa) 101 { 102 Splay(x); 103 x->ch[1]=r; 104 } 105 } 106 void MoveRoot(node *x) {Access(x); Splay(x); x->rev^=1;} 107 void Split(node *x,node *y) {MoveRoot(x); Access(y); Splay(y);} 108 void Link(node *x,node *y) {MoveRoot(x); x->fa=y;} 109 void Cut(node *x,node *y) {Split(x,y); y->ch[0]->fa=null; y->ch[0]=null;} 110 void Change(node *x,int v) {Splay(x); x->data=v; x->push_up();} 111 void Data_Rev(node *x,node *y) {Split(x,y); int k=y->maxn; y->data=-y->data; y->sum=-y->sum; y->maxn=-y->minn; y->minn=-k; y->rev_data^=1; } 112 int Query_Sum(node *x,node *y) {Split(x,y); return y->sum;} 113 int Query_Max(node *x,node *y) {Split(x,y); return y->maxn;} 114 int Query_Min(node *x,node *y) {Split(x,y); return y->minn;} 115 } 116 inline int read() 117 { 118 char c; 119 int ans=0,f=1; 120 while (!isdigit(c=getchar())) {if (c=='-') f=-1;} 121 ans=c-'0'; 122 while (isdigit(c=getchar())) ans=ans*10+c-'0'; 123 return ans*f; 124 } 125 void init() 126 { 127 null=pt++; 128 null->fa=null->ch[0]=null->ch[1]=null; 129 null->data=null->sum=0; 130 null->rev=null->rev_data=null->ie=0; 131 null->maxn=-inf; null->minn=inf; 132 } 133 using namespace LCT; 134 int main() 135 { 136 // freopen("travel.in","r",stdin); 137 // freopen("travel.out","w",stdout); 138 int x,y,z; 139 n=read(); 140 init(); 141 for (int i=0;i<n;i++) p[i]=NewNode(0,0); 142 for (int i=1;i<n;i++) 143 { 144 x=read(); y=read(); z=read(); 145 e[i]=NewNode(z,1); 146 Link(p[x],e[i]);Link(e[i],p[y]); 147 } 148 m=read(); 149 char s[10]; 150 for (int i=1;i<=m;i++) 151 { 152 scanf("%s",s); 153 x=read(); y=read(); 154 if (s[0]=='C') Change(e[x],y); 155 if (s[0]=='N') Data_Rev(p[x],p[y]); 156 if (s[0]=='S') printf("%d\n",Query_Sum(p[x],p[y])); 157 if (s[0]=='M') 158 if (s[1]=='A') printf("%d\n",Query_Max(p[x],p[y])); 159 else printf("%d\n",Query_Min(p[x],p[y])); 160 } 161 return 0; 162 }
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),输出答案。