二次联通门 : COGS 1583. [POJ3237]树的维护

/*
COGS 1583. [POJ3237]树的维护 树链剖分 + 边权化点权
线段树 单点修改 + 区间取相反数 + 查询区间最大 对于区间取相反数
考虑在线段树中维护两个值
一个区间最大, 一个区间最小
对于更改, 只需把区间最大与最小分别取相反数后交换即可 然后对于标记, 由于对区间连续取反两次相当于不变
则只需开一个bool 标记, 每次放标记时对标记取反即可 */
#include <cstdio> #define INF 1e7
#define Max 20005 inline int max (int a, int b)
{
return a > b ? a : b;
} inline int min (int a, int b)
{
return a < b ? a : b;
} inline int swap (int &a, int &b)
{
int now = a;
a = b;
b = now;
} void read (int &now)
{
now = ;
bool temp = false;
register char word = getchar ();
while (word < '' || word > '')
{
if (word == '-')
temp = true;
word = getchar ();
}
while (word <= '' && word >= '')
{
now = now * + word - '';
word = getchar ();
}
} int tree_value[Max]; class Segment_Tree_Type
{
private : struct Tree_Date
{
int l;
int r;
int Maxn;
int Minn;
int Mid;
bool Flandre_Scarlet;
}
tree[Max << ]; public : void Build (int l, int r, int now)
{
tree[now].l = l;
tree[now].r = r;
if (l == r)
{
tree[now].Maxn = tree_value[l];
tree[now].Minn = tree_value[r];
return ;
}
tree[now].Mid = l + r >> ;
Build (l, tree[now].Mid, now << );
Build (tree[now].Mid + , r, now << | );
tree[now].Maxn = max (tree[now << ].Maxn, tree[now << | ].Maxn);
tree[now].Minn = min (tree[now << ].Minn, tree[now << | ].Minn);
} int Query_Section (int l, int r, int now)
{
if (tree[now].l == l && tree[now].r == r)
return tree[now].Maxn;
if (tree[now].Flandre_Scarlet)
{
tree[now << ].Maxn = -tree[now << ].Maxn;
tree[now << | ].Maxn = -tree[now << | ].Maxn;
tree[now << ].Minn = -tree[now << ].Minn;
tree[now << | ].Minn = -tree[now << | ].Minn;
swap (tree[now << ].Maxn, tree[now << ].Minn);
tree[now << ].Flandre_Scarlet = !tree[now << ].Flandre_Scarlet;
swap (tree[now << | ].Maxn, tree[now << | ].Minn);
tree[now << | ].Flandre_Scarlet = !tree[now << | ].Flandre_Scarlet;
tree[now].Flandre_Scarlet = false;
}
tree[now].Maxn = max (tree[now << ].Maxn, tree[now << | ].Maxn);
tree[now].Minn = min (tree[now << ].Minn, tree[now << | ].Minn);
if (r <= tree[now].Mid)
return Query_Section (l, r, now << );
else if (l > tree[now].Mid)
return Query_Section (l, r, now << | );
else
return max (Query_Section (l, tree[now].Mid, now << ), Query_Section (tree[now].Mid + , r, now << | ));
} void Change_Section (int l, int r, int now)
{
if (tree[now].l == l && tree[now].r == r)
{
tree[now].Maxn = -tree[now].Maxn;
tree[now].Minn = -tree[now].Minn;
swap (tree[now].Maxn, tree[now].Minn);
tree[now].Flandre_Scarlet = !tree[now].Flandre_Scarlet;
return ;
}
if (tree[now].Flandre_Scarlet)
{
tree[now << ].Maxn = -tree[now << ].Maxn;
tree[now << | ].Maxn = -tree[now << | ].Maxn;
tree[now << ].Minn = -tree[now << ].Minn;
tree[now << | ].Minn = -tree[now << | ].Minn;
swap (tree[now << ].Maxn, tree[now << ].Minn);
tree[now << ].Flandre_Scarlet = !tree[now << ].Flandre_Scarlet;
swap (tree[now << | ].Maxn, tree[now << | ].Minn);
tree[now << | ].Flandre_Scarlet = !tree[now << | ].Flandre_Scarlet;
tree[now].Flandre_Scarlet = false;
}
if (r <= tree[now].Mid)
Change_Section (l, r, now << );
else if (l > tree[now].Mid)
Change_Section (l, r, now << | );
else
{
Change_Section (l, tree[now].Mid, now << );
Change_Section (tree[now].Mid + , r, now << | );
}
tree[now].Maxn = max (tree[now << ].Maxn, tree[now << | ].Maxn);
tree[now].Minn = min (tree[now << ].Minn, tree[now << | ].Minn);
} void Change_Single (int pos, int now, int number)
{
if (tree[now].l == tree[now].r)
{
tree[now].Maxn = number;
tree[now].Minn = number;
return;
}
if (tree[now].Flandre_Scarlet)
{
tree[now << ].Maxn = -tree[now << ].Maxn;
tree[now << | ].Maxn = -tree[now << | ].Maxn;
tree[now << ].Minn = -tree[now << ].Minn;
tree[now << | ].Minn = -tree[now << | ].Minn;
swap (tree[now << ].Maxn, tree[now << ].Minn);
tree[now << ].Flandre_Scarlet = !tree[now << ].Flandre_Scarlet;
swap (tree[now << | ].Maxn, tree[now << | ].Minn);
tree[now << | ].Flandre_Scarlet = !tree[now << | ].Flandre_Scarlet;
tree[now].Flandre_Scarlet = false;
}
if (pos <= tree[now].Mid)
Change_Single (pos, now << , number);
else
Change_Single (pos, now << | , number);
tree[now].Maxn = max (tree[now << ].Maxn, tree[now << | ].Maxn);
tree[now].Minn = min (tree[now << ].Minn, tree[now << | ].Minn);
}
}; Segment_Tree_Type Segment_Tree; class Tree_Chain_Type
{
private : struct Edge_Date
{
int to;
int next;
int key;
int from;
}
edge[Max << ]; struct Point_Date
{
int size;
int father;
int up_chain_point;
int deep;
int segment_tree_pos;
}
point[Max]; int Edge_Count;
int edge_list[Max];
int Segment_Pos;
int Count; public : inline int Add_Edge (int from, int to, int dis)
{
Edge_Count++;
edge[Edge_Count].to = to;
edge[Edge_Count].from = from;
edge[Edge_Count].next = edge_list[from];
edge_list[from] = Edge_Count;
edge[Edge_Count].key = dis;
Edge_Count++;
edge[Edge_Count].to = from;
edge[Edge_Count].from = to;
edge[Edge_Count].next = edge_list[to];
edge_list[to] = Edge_Count;
edge[Edge_Count].key = dis;
} void Dfs_1 (int now, int father)
{
int pos = Count++;
point[now].father = father;
point[now].deep = point[father].deep + ;
for (int i = edge_list[now]; i; i = edge[i].next)
if (edge[i].to != father)
Dfs_1 (edge[i].to, now);
point[now].size = Count - pos;
} void Dfs_2 (int now, int chain)
{
point[now].segment_tree_pos = ++Segment_Pos;
for (int i = edge_list[now]; i; i = edge[i].next)
if (edge[i].to == point[now].father)
{
tree_value[Segment_Pos] = edge[i].key;
break;
}
point[now].up_chain_point = chain;
int pos = ;
for (int i = edge_list[now]; i; i = edge[i].next)
if (!point[edge[i].to].segment_tree_pos && point[edge[i].to].size > point[pos].size)
pos = edge[i].to;
if (!pos)
return;
Dfs_2 (pos, chain);
for (int i = edge_list[now]; i; i = edge[i].next)
if (!point[edge[i].to].segment_tree_pos && edge[i].to != pos)
Dfs_2 (edge[i].to, edge[i].to);
} int Query_chain (int x, int y)
{
int Answer = -INF;
while (point[x].up_chain_point != point[y].up_chain_point)
{
if (point[point[x].up_chain_point].deep < point[point[y].up_chain_point].deep)
swap (x, y);
Answer = max (Answer, Segment_Tree.Query_Section (point[point[x].up_chain_point].segment_tree_pos, point[x].segment_tree_pos, ));
x = point[point[x].up_chain_point].father;
}
if (point[x].deep > point[y].deep)
swap (x, y);
if (x != y)
Answer = max (Answer, Segment_Tree.Query_Section (point[x].segment_tree_pos + , point[y].segment_tree_pos, ));
return Answer;
} void Change_chain (int x, int y)
{
while (point[x].up_chain_point != point[y].up_chain_point)
{
if (point[point[x].up_chain_point].deep < point[point[y].up_chain_point].deep)
swap (x, y);
Segment_Tree.Change_Section (point[point[x].up_chain_point].segment_tree_pos, point[x].segment_tree_pos, );
x = point[point[x].up_chain_point].father;
}
if (point[x].deep > point[y].deep)
swap (x, y);
if (x != y)
Segment_Tree.Change_Section (point[x].segment_tree_pos + , point[y].segment_tree_pos, );
} void Change_Single (int x, int number)
{
x = (x << ) - ;
int pos = point[edge[x].to].deep > point[edge[x].from].deep ? point[edge[x].to].segment_tree_pos : point[edge[x].from].segment_tree_pos;
Segment_Tree.Change_Single (pos, , number);
return ;
}
}; Tree_Chain_Type Make; int main (int argc, char *argv[])
{
freopen ("maintaintree.in", "r", stdin);
freopen ("maintaintree.out", "w", stdout);
int N;
read (N);
int x, y, z;
for (int i = ; i < N; i++)
{
read (x);
read (y);
read (z);
Make.Add_Edge (x, y, z);
}
Make.Dfs_1 (, );
Make.Dfs_2 (, );
Segment_Tree.Build (, N, );
char type[];
while (scanf ("%s", type) && type[] != 'D')
{
read (x);
read (y);
if (type[] == 'Q')
printf ("%d\n", Make.Query_chain (x, y));
else if (type[] == 'C')
Make.Change_Single (x, y);
else
Make.Change_chain (x, y);
}
return ;
}

COGS 1583. [POJ3237]树的维护的更多相关文章

  1. Cogs 1583. [POJ3237]树的维护 LCT,树链剖分

    题目:http://cojs.tk/cogs/problem/problem.php?pid=1583 1583. [POJ3237]树的维护 ★★★☆   输入文件:maintaintree.in  ...

  2. cogs1583. [POJ3237]树的维护

    1583. [POJ3237]树的维护 http://www.cogs.pro/cogs/problem/problem.php?pid=1583 ★★★☆   输入文件:maintaintree.i ...

  3. cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树

    1583. [POJ 3237] 树的维护 ★★★★   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比时间限制:5 s   内存限制:128 ...

  4. poj3237 树链部分 边权模板

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7384   Accepted: 2001 Description ...

  5. 【bzoj3533】[Sdoi2014]向量集 线段树+STL-vector维护凸包

    题目描述 维护一个向量集合,在线支持以下操作:"A x y (|x|,|y| < =10^8)":加入向量(x,y);"Q x y l r (|x|,|y| < ...

  6. hdu 1556 Color the ball(线段树区间维护+单点求值)

    传送门:Color the ball Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/3276 ...

  7. 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))

    函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...

  8. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  9. CodeForces 587 E.Duff as a Queen 线段树动态维护区间线性基

    https://codeforces.com/contest/587/problem/E 一个序列, 1区间异或操作 2查询区间子集异或种类数 题解 解题思路大同小异,都是利用异或的性质进行转化,st ...

随机推荐

  1. 分享大麦UWP版本开发历程-03.GridView或ListView 滚动底部自动加载后续数据

    今天跟大家分享的是大麦UWP客户端,在分类.订单或是搜索时都用到的一个小技巧,技术粗糙大神勿喷. 以大麦分类举例,默认打开的时候,会为用户展示20条数据,当用户滚动鼠标或者使用手势将列表滑动到倒数第二 ...

  2. SpringCloud--1--服务治理Eureka

    一.Eureka概述 1.Eureka特点 只需通过简单引入依赖和注解配置,就能让SpringBoot构建的微服务应用轻松地与Eureka服务治理体系进行整合. Eureka负责服务治理,即:微服务实 ...

  3. Java隐式类型转换和强制类型转换

    一.强制类型转换 char 和 整型之间的类型转换 char a7 = 'a'; System.out.println(a7); System.out.println( (int)a7 ); Syst ...

  4. 【转载】C#中通过Distinct方法对List集合进行去重

    在C#的List集合对象中,可以使用Distinct方法来对List集合元素进行去重,如果list集合内部元素为值类型,则Distinct方法根据值类型是否相等来判断去重,如果List集合内部元素为引 ...

  5. canvas教程(二) 绘制直线

    经过 canvas 教程(一) 简介 我们知道了 canvas 的一些基本情况 而本次是给大家带来直线的绘制 canvas 中,基本图形有两种,一种是直线,还有一种是曲线 但是无论是直线还是曲线,我们 ...

  6. border-radius圆角属性

    border-radius圆角 当盒子的宽高一样时,设置盒子的border-radius为50%,得到一个圆形 border-radius: 20px 30px 200px 200px; 只写一个值: ...

  7. Java关于 class类的基础方法

    Class类的方法 1. getClasses 和 getDeclaredClasses getDeclaredClasses 获取到类里所有的的class ,interface 包括了private ...

  8. Nginx 操作响应头信息的实现

    前置条件:需要编译 ngx_http_headers_module 模块,才支持 header 头信息操作 add_header 意思为将自定义的头信息的添加到响应头,指令为 add_header n ...

  9. go语言实现限流器

    本文:https://chai2010.cn/advanced-go-programming-book/ch5-web/ch5-06-ratelimit.html Ratelimit 服务流量限制 计 ...

  10. 微信小程序---客服消息接口调用,拿来即用

    如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人.谢谢大家!❤ 如果解决不了,可以在文末进群交流. 如果对你有帮助的话麻烦点个[推荐]~最好还可以follow一下我的GitHub~感谢观看! 在 ...