二次联通门 : 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. Redis Streams与Spark的完美结合

    来源:Redislabs 作者:Roshan Kumar 翻译:Kevin  (公众号:中间件小哥) 最近,我有幸在 Spark +AI 峰会上发表了题目为“Redis + Structured St ...

  2. ORACLE数据库实现自增的两种方式

    Mysql数据库因为其有自动+1,故一般我们不需要花费太多时间,直接用关键字auto_increment即可,但是Oracle不行,它没有自动增长机制.顾我们需要自己去实现.一般有两种方式,但是这两种 ...

  3. SpringBoot指定额外需要扫描的包

    我们都知道,SpringBoot主启动类标注了@SpringBootApplication注解,该注解引入了@ComponentScan注解 所以默认的包扫描规则是,程序会自动扫描主启动类所在包及其子 ...

  4. error LNK2005: “找到一个或多个多重定义的符号” 已经在 xxxx.obj 中定义 的解决方法

    1 问题还原 这里我有三个源文件:Base.hpp, Base.cpp 和 main.cpp 在Base.hpp里面定义一个基类,注意,基类只包含构造函数和析构函数的声明,函数在Base.cpp里实现 ...

  5. 【转】常见的tcp/ip协议的知识

    1.tcp/ip协议的层数 左图是osi 7层模型,右图是tcp/ip 4层模型.二者对应关系如上. 2.socket中TCP的三次握手建立连接详解 我们知道tcp建立连接要进行“三次握手”,即交换三 ...

  6. mysql 优化修复表

    OPTIMIZE TABLE `table_name` 优化表 MyISAM 引擎清理碎片 OPTIMIZE语法: OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABL ...

  7. SSH安全协议

    SSHD服务 介绍:SSH 协议:安全外壳协议.为 Secure Shell 的缩写.SSH 为建立在应用层和传输层基础上的安全协议. 默认端口22 作用 sshd服务使用SSH协议可以用来进行远程控 ...

  8. MySQL加锁分析 (转)

    参考:MySQL 加锁处理分析.该文已经讲的很详尽了,也易懂,下面仅仅是个人做的总结. 一. 背景 1.1 隔离级别 1.2 加锁过程 逐条处理,逐条加锁. 1.3 两阶段锁2PL 1.4 gap锁 ...

  9. jmeter + ant + jenkins 自动化集成环境搭建

    所需工具 一.jmeter 工具下载 https://jmeter.apache.org/  配置环境JDK等及各种插件 二.Ant安装(http://ant.apache.org/) 安装Ant是为 ...

  10. Linux关闭防火墙、设置端口

    关闭防火墙 1)重启后生效 开启: chkconfig iptables on 关闭: chkconfig iptables off 验证防火墙是否关闭:chkconfig --list |grep ...