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 ...
随机推荐
- promethus监控nginx
一.摘要 promethues监控nginx可选两个exporter,通过nginx_exporter主要是获取nginx-status中的内建的指标,nginx自身提供status信息,较为简单,p ...
- windows10 iis浏览wcf报404.3错误
报错:HTTP错误404.3-Not Found 由于扩展配置问题而无法提供您请求的页面.如果该页面是脚本,请添加处理程序.如果应下载文件,请添加MIME映射. 解决步骤如下: 控制面板->打开 ...
- 2.5_Database Interface ODBC数据源及案例
分类 用户数据源 用户创建的数据源,称为“用户数据源”.此时只有创建者才能使用,并且只能在所定义的机器上运行.任何用户都不能使用其他用户创建的用户数据源. 系统数据源 所有用户在Windows下以服务 ...
- Python之TensorFlow的变量收集、自定义命令参数、矩阵运算、梯度下降-4
一.TensorFlow为什么要存在变量收集的过程,主要目的就是把训练过程中的数据,比如loss.权重.偏置等数据通过图形展示的方式呈现在开发者的眼前. 自定义参数:自定义参数,主要是通过Python ...
- JSON C# Class Generator
http://www.xamasoft.com/json-class-generator/ JsonHelper.cs using System; using System.Collections.G ...
- Python多版本环境搭建(Linux系统)
python Linux 环境 (版本隔离工具) 首先新建用户,养成良好习惯 useradd python 1.安装pyenv GitHub官网: https://github.c ...
- Spring Boot 笔记 (2) - 使用 log4j2 记日志
日志框架的选用 Spring 使用的默认日志框架是 logback, 默认情况下会采取默认的 autoconfiguration; 即便想对日志的一些配置进行修改也比较方便, 详细可以参考: Spri ...
- eclipse debug问题
出现上面的问题 可能是电脑了 工具栏的run >skip all Breakpoint : 解决办法 再点一次: Eclipse debug不跳转 解决办法
- HTML&CSS基础-属性选择器
HTML&CSS基础-属性选择器 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.html源代码 <!DOCTYPE html> <html> & ...
- Scrum会议博客以及测试报告(β阶段)
3组Alpha冲刺阶段博客目录 一.Scrum Meeting1. [第十周会议记录](链接地址:https://www.cnblogs.com/Cherrison-Time/articles/120 ...