COGS 1583. [POJ3237]树的维护
二次联通门 : 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]树的维护的更多相关文章
- Cogs 1583. [POJ3237]树的维护 LCT,树链剖分
题目:http://cojs.tk/cogs/problem/problem.php?pid=1583 1583. [POJ3237]树的维护 ★★★☆ 输入文件:maintaintree.in ...
- cogs1583. [POJ3237]树的维护
1583. [POJ3237]树的维护 http://www.cogs.pro/cogs/problem/problem.php?pid=1583 ★★★☆ 输入文件:maintaintree.i ...
- cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树
1583. [POJ 3237] 树的维护 ★★★★ 输入文件:maintaintree.in 输出文件:maintaintree.out 简单对比时间限制:5 s 内存限制:128 ...
- poj3237 树链部分 边权模板
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 7384 Accepted: 2001 Description ...
- 【bzoj3533】[Sdoi2014]向量集 线段树+STL-vector维护凸包
题目描述 维护一个向量集合,在线支持以下操作:"A x y (|x|,|y| < =10^8)":加入向量(x,y);"Q x y l r (|x|,|y| < ...
- hdu 1556 Color the ball(线段树区间维护+单点求值)
传送门:Color the ball Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/3276 ...
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- CodeForces 587 E.Duff as a Queen 线段树动态维护区间线性基
https://codeforces.com/contest/587/problem/E 一个序列, 1区间异或操作 2查询区间子集异或种类数 题解 解题思路大同小异,都是利用异或的性质进行转化,st ...
随机推荐
- [国家集训队] JZPKIL
题目链接 洛谷:https://www.luogu.org/problemnew/show/P4464 Solution 这题是真的毒....数论大杂烩,窝断断续续写了两天. 众所周知: \[ {\r ...
- go 基本IO接口
package main import ( "fmt" "io" "strings" ) func ReadFrom(reader io.R ...
- core文件问题
core文件问题 Linux系统core涉及到的问题 core文件的问题具体可以参照系统的man手册(man core) 能否生成core文件 ulimit -c 磁盘权限问题 进程权限问题 生成co ...
- 论文笔记 XGBoost: A Scalable Tree Boosting System
XGBoost是boosting算法的其中一种.Boosting算法的思想是将许多弱分类器集成在一起形成一个强分类器,其更关注与降低基模型的偏差.XGBoost是一种提升树模型(Gradient bo ...
- 【洛谷 P2597】 [ZJOI2012]灾难(LCA)
题目链接 考虑建一棵树,使一个生物灭绝时他的子树都会灭绝,显然这样答案就是以每个点为根的子树大小-1. 为什么原图不是一棵树,因为一个生物可能会以多个生物为食,所以按拓扑序来建树,把每个遍历到的点的父 ...
- 刚接触HTML5应该先学哪里才好?
好吧,话不多说,直接来点干货吧! 刚接触html的小白都感觉摸不着头脑?应该怎么学习呢,其实HTML5可能对于还没有接触过的小白来说会比较的难,听起来也比较新颖.这是个什么骚东西!其实不然,这个就是构 ...
- Node.js学习之(第二章:exports和module.exports)
前言 Node中,每个模块都有一个exports接口对象,我们需要把公共的方法或者字符串挂载在这个接口对象中,其他的模块才可以使用. Node.js中只有模块作用域,默认两个模块之间的变量,方法互不冲 ...
- 记支付宝接口对接,涉及到提取证书SN号的解决方案
支付宝针对.NET SDK并未封装有提取证书SN序列号的方法,仅针对Java平台才有对应的方法(赤裸裸的歧视啊~~) 要想在提取这个SN序列号有两种方案: 1. 直接用Java SDK包来提取SN 2 ...
- 如何使用adb工具在电脑上使用程序的方式操控自己的android手机
在电脑安装adb工具: sudo apt install android-tools-adb android-tools-fastboot# 检查是否成功adb version 开启adb服务 sud ...
- 【HCIA Gauss】学习汇总-数据库管理(数据库基本概念)-3
数据库:操作系统文件或磁盘数据块的集合数据库实例: 指操作系统中一系列进程以及为这些进程分配的内存块 通常来说一个数据库实例对应着一个数据库[数据库实例是访问数据的通道] 多实例:利用多实例 可以充分 ...