[BZOJ2157] 旅游 树链剖分
2017-08-16 22:43
405 查看
模板题,没什么好说的
#include<vector> #include<cstdio> #include<cstring> #include<climits> #include<iostream> #include<algorithm> using namespace std; const int Lim = 150005; int n , m; vector<int> edge[Lim]; struct E {int a , b , c;} e[Lim]; namespace Dfsing{ int prt[Lim] , son[Lim] , depth[Lim]; int number[Lim] , siz[Lim] , top[Lim]; int sign; void Dfs_first(int x) { int Maxson = 0; siz[x] = 1; for(int i=0,y ; i<(int)edge[x].size() ; i++) if( (y = edge[x][i]) != prt[x]) { prt[y] = x; depth[y] = depth[x] + 1; Dfs_first(y); siz[x] += siz[y]; if(siz[y] > Maxson) son[x] = y , Maxson = siz[y]; } } void Dfs_second(int x , int Top_now) { top[x] = Top_now; number[x] = ++sign; if(son[x]) Dfs_second(son[x] , Top_now); for(int i=0 ; i<(int)edge[x].size() ; i++) { int y = edge[x][i]; if(y == prt[x] || y == son[x]) continue; Dfs_second(y , y); } } } using namespace Dfsing; namespace Segment_Tree{ struct Seg{ int a , b , Maxx , Minn , sum , rev; } tree[Lim * 4]; void Build(int v , int L , int R) { tree[v] = (Seg) {L , R , INT_MIN , INT_MAX , 0 , 0}; if(L == R) return; int mid = (L + R) >> 1; Build(v<<1 , L , mid) , Build(v<<1|1 , mid+1 , R); } void Pushdown(int v) { if(tree[v].rev && (tree[v].a != tree[v].b)) { int Ls = v<<1 , Rs = v<<1|1; tree[Ls].Maxx *= -1 , tree[Ls].Minn *= -1 , tree[Ls].sum *= -1; swap(tree[Ls].Maxx , tree[Ls].Minn); tree[Ls].rev ^= 1; /*2ed*/ tree[Rs].Maxx *= -1 , tree[Rs].Minn *= -1 , tree[Rs].sum *= -1; swap(tree[Rs].Maxx , tree[Rs].Minn); tree[Rs].rev ^= 1; tree[v].rev = 0; /*1st*/ } } void Pushup(int v) { tree[v].Maxx = max(tree[v<<1].Maxx , tree[v<<1|1].Maxx); tree[v].Minn = min(tree[v<<1].Minn , tree[v<<1|1].Minn); tree[v].sum = tree[v<<1].sum + tree[v<<1|1].sum; } void Modify(int v , int goal , int d) { if(tree[v].a > goal || tree[v].b < goal) return; if(tree[v].a == goal && tree[v].b == goal) { tree[v].Maxx = tree[v].Minn = tree[v].sum = d; tree[v].rev = 0; return; } Pushdown(v); Modify(v<<1 , goal , d) , Modify(v<<1|1 , goal , d); Pushup(v); } void Reverse(int v , int L , int R) { if(tree[v].a > R || tree[v].b < L) return; if(tree[v].a >= L && tree[v].b <= R) { tree[v].Maxx *= -1; tree[v].Minn *= -1; tree[v].sum *= -1; swap(tree[v].Maxx , tree[v].Minn); tree[v].rev ^= 1; return; } Pushdown(v); Reverse(v<<1 , L , R) , Reverse(v<<1|1 , L , R); Pushup(v); } int Get_Sum(int v , int L , int R) { if(tree[v].a > R || tree[v].b < L) return 0; if(tree[v].a >= L && tree[v].b <= R) return tree[v].sum; Pushdown(v); int t1 = Get_Sum(v<<1 , L , R) , t2 = Get_Sum(v<<1|1 , L , R); Pushup(v); return t1 + t2; } int Get_Max(int v , int L , int R) { if(tree[v].a > R || tree[v].b < L) return INT_MIN; if(tree[v].a >= L && tree[v].b <= R) return tree[v].Maxx; Pushdown(v); int t1 = Get_Max(v<<1 , L , R) , t2 = Get_Max(v<<1|1 , L , R); Pushup(v); return max(t1 , t2); } int Get_Min(int v , int L , int R) { if(tree[v].a > R || tree[v].b < L) return INT_MAX; if(tree[v].a >= L && tree[v].b <= R) return tree[v].Minn; Pushdown(v); int t1 = Get_Min(v<<1 , L , R) , t2 = Get_Min(v<<1|1 , L , R); Pushup(v); return min(t1 , t2); } } using namespace Segment_Tree; namespace Problems{ void Neg(int u , int v) { int f1 = top[u] , f2 = top[v]; while(f1 != f2) { if(depth[f1] < depth[f2]) {swap(f1 , f2); swap(u,v);} Reverse(1 , number[f1] , number[u]); u = prt[f1] , f1 = top[u]; } if(u == v) return; if(depth[u] > depth[v]) swap(u , v); Reverse(1 , number[son[u]] , number[v]); } bc59 int Ask_Sum(int u , int v) { int f1 = top[u] , f2 = top[v] , sum = 0; while(f1 != f2) { if(depth[f1] < depth[f2]) {swap(f1 , f2); swap(u,v);} sum += Get_Sum(1 , number[f1] , number[u]); u = prt[f1] , f1 = top[u]; } if(u == v) return sum; if(depth[u] > depth[v]) swap(u , v); return (sum + Get_Sum(1 , number[son[u]] , number[v])); } int Ask_M(int u , int v , int way) { int f1 = top[u] , f2 = top[v]; int ans = way == 1 ? INT_MIN : INT_MAX; while(f1 != f2) { if(depth[f1] < depth[f2]) {swap(f1 , f2); swap(u,v);} if(way == 1) ans = max(ans , Get_Max(1 , number[f1] , number[u])); else ans = min(ans , Get_Min(1 , number[f1] , number[u])); u = prt[f1] , f1 = top[u]; } if(u == v) return ans; if(depth[u] > depth[v]) swap(u , v); if(way == 1) ans = max(ans , Get_Max(1 , number[son[u]] , number[v])); else ans = min(ans , Get_Min(1 , number[son[u]] , number[v])); return ans; } } using namespace Problems; void Solve() { char order[10]; scanf("%d",&m); int u , v; while(m--) { scanf("%s %d %d",order,&u,&v); u++ , v++; if(order[0] == 'C') Modify(1 , number[e[u-1].a] , v-1); else if(order[0] == 'N') Neg(u , v); else if(order[0] == 'S') printf("%d\n",Ask_Sum(u , v)); else { if(order[1] == 'A') printf("%d\n",Ask_M(u , v , 1)); else printf("%d\n",Ask_M(u , v ,2)); } } } int main() { scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%d %d %d",&e[i].a,&e[i].b,&e[i].c); e[i].a++ , e[i].b++; edge[e[i].a].push_back(e[i].b); edge[e[i].b].push_back(e[i].a); } depth[1] = 1; Dfs_first(1); Dfs_second(1 , 1); Build(1 , 1 , sign); for(int i=1;i<n;i++) { if(depth[e[i].a] < depth[e[i].b]) swap(e[i].a , e[i].b); Modify(1 , number[e[i].a] , e[i].c); } Solve(); return 0; }
相关文章推荐
- [bzoj2157][树链剖分]旅游
- 【BZOJ2157】旅游(树链剖分,Link-Cut Tree)
- 【BZOJ2157】旅游,树链剖分练习
- bzoj2157 旅游(树链剖分)
- bzoj 2157: 旅游【树链剖分+线段树】
- BZOJ 2157 旅游 树链剖分
- 【树链剖分】【线段树】bzoj2157 旅游
- BZOJ 2157: 旅游 树链剖分
- BZOJ 2157: 旅游 树链剖分
- bzoj2157 旅游 树链剖分
- 【树链剖分】【bzoj2157】: 旅游
- BZOJ 2157 旅游 树链剖分
- BZOJ[2157]旅游 树链剖分+线段树
- 【bzoj2157】旅游
- BZOJ 2157 旅游(动态树)
- bzoj 3999: [TJOI2015]旅游(树链剖分)
- 【BZOJ3999】旅游,树链剖分中的有向信息合并
- bzoj:3999 [TJOI2015]旅游(树链剖分)
- bzoj 2157: 旅游 树链剖分+线段树
- [BZOJ2157]旅游