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 ...
随机推荐
- docker相关--开始使用swarm模式
Swarm简介 Swarm是Docker的一个编排工具,参考官网:https://docs.docker.com/engine/swarm/ Swarm 模式简介 要在Swarm模式下运行docker ...
- c# 异步( Async ) 不是多线程
c# 异步( Async ) 不是多线程 误解 async 在调试 xxxxAsync() 方法的时候,常常会看到调试器界面中会多出一些线程,直觉上误认为 Async 冠名的函数是多线程. 对于 ...
- bat 设置多个静态ip
@echo off REM 本地连接名称 set NetName="本地连接 2" REM 默认IP netsh interface ipv4 set address name=% ...
- jupyter安装出现问题:安装后无法打开
jupyter安装出现问题:安装后无法打开 traitlets.traitlets.TraitError: Could not decode 'C:\Users\\xce\xa2\xcc\xf0\xd ...
- Air for ANE:打包注意的地方
来源:http://blog.csdn.net/hero82748274/article/details/8631982 今天遇到了一个打包ANE 文件的问题,导致花费了几个小时查找,最后师弟的一句话 ...
- MySQL Lock--MySQL加锁学习1
准备测试数据: ## 开启InnoDB Monitor SET GLOBAL innodb_status_output=ON; SET GLOBAL innodb_status_output_lock ...
- mybatis中如何将多个表的查询结果,放入结果集中返回
1.首先需要将resultMap进行改造,为了避免对其他sql的影响建议另外定义一个resultMapExtral,避免id相同, 2.然后在resultMapExtral中添加其它表的字段,若多个表 ...
- WIN8输入法的问题
在win8下输入法的添加和删除,使用第三方的软件很难处理好,而且容易造成系统的不稳定.比如搜狗输入法有个输入法管理器. 正确的做法: 1.Win+C打开侧边栏,点击 设置,选择“更改电脑设置” 这个选 ...
- oracle添加序列
原文地址 http://blog.itpub.net/24099965/viewspace-1116923/ 1.创建.删除 create sequence seq_newsId increment ...
- node gm图片操作
1,安首先要安装 GraphicsMagick或者ImageMagick 2,npm install gm --save 3,编码测试 var fs = require('fs') //graph ...