您的位置:首页 > 其它

[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: