cogs1583. [POJ3237]树的维护
1583. [POJ3237]树的维护
http://www.cogs.pro/cogs/problem/problem.php?pid=1583
★★★☆ 输入文件:maintaintree.in 输出文件:maintaintree.out 简单对比
时间限制:5 s 内存限制:128 MB
【题目描述】
给你由N个结点组成的树。树的节点被编号为1到N,边被编号为1到N-1。每一条边有一个权值。然后你要在树上执行一系列指令。指令可以是如下三种之一:
CHANGE i v:将第i条边的权值改成v。
NEGATE a b:将点a到点b路径上所有边的权值变成其相反数。
QUERY a b:找出点a到点b路径上各边的最大权值。
【输入格式】
输入文件的第一行有一个整数N(N<=10000)。
接下来N-1行每行有三个整数a,b,c,代表点a和点b之间有一条权值为c的边。这些边按照其编号从小到大给出。
接下来是若干条指令(不超过10^5条),都按照上面所说的格式。
输入文件的最后一行是"DONE".
【输出格式】
对每个“QUERY”指令,输出一行,即路径上各边的最大权值。
【样例输入】
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
【样例输出】
1
3
【提示】
这里的输入输出格式和POJ上原题略有不同。
【来源】
难点在于取相反数操作
记录下最大值和最小值,有取相反数操作时,就把两个值变成相反数,再交换两数的值就ok,然后给这个区间打上标记(线段树的lazy标记),以后访问或更改值时记得下传标记就好。
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std; const int MAXN = ;
struct Edge{
int to,next;
}edge[MAXN*];
int head[MAXN],tot;
int top[MAXN];//top[v]表示v所在的重链的顶端节点
int fa[MAXN]; //父亲节点
int deep[MAXN];//深度
int num[MAXN];//num[v]表示以v为根的子树的节点数
int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置
int fp[MAXN];//和p数组相反
int son[MAXN];//重儿子
int pos;
void init(){
tot = ;
memset(head,-,sizeof(head));
pos = ;
memset(son,-,sizeof(son));
}
void addedge(int u,int v){
edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;
}
void dfs1(int u,int v,int d){
deep[v]=d;
fa[v]=u;
num[v]=;
for(int i=head[v];i!=-;i=edge[i].next){
int to=edge[i].to;
if(to==u)continue;
dfs1(v,to,d+);
num[v]+=num[to];
if(son[v]==-||num[son[v]]<num[to])son[v]=to;
}
}
void dfs2(int u,int v){
top[u]=v;
p[u]=pos++;
if(son[u]==-)return;
dfs2(son[u],v);
for(int i=head[u];i!=-;i=edge[i].next){
int to=edge[i].to;
if(to==fa[u]||to==son[u])continue;
dfs2(to,to);
}
} //线段树
struct Node{
int l,r;
int Max;
int Min;
int ne;
}tr[MAXN*];
void build(int i,int l,int r){
tr[i].l = l;
tr[i].r = r;
tr[i].Max = ;
tr[i].Min = ;
tr[i].ne = ;
if(l == r)return;
int mid = (l+r)/;
build(i<<,l,mid);
build((i<<)|,mid+,r);
}
void push_up(int i)
{
tr[i].Max = max(tr[i<<].Max,tr[(i<<)|].Max);
tr[i].Min = min(tr[i<<].Min,tr[(i<<)|].Min);
}
void push_down(int i){ if(tr[i].l == tr[i].r)return;
if(tr[i].ne)
{
tr[i<<].Max = -tr[i<<].Max;
tr[i<<].Min = -tr[i<<].Min;
swap(tr[i<<].Min,tr[i<<].Max);
tr[(i<<)|].Max = -tr[(i<<)|].Max;
tr[(i<<)|].Min = -tr[(i<<)|].Min;
swap(tr[(i<<)|].Max,tr[(i<<)|].Min);
tr[i<<].ne ^= ;
tr[(i<<)|].ne ^= ;
tr[i].ne = ;
}
}
void update(int i,int k,int val){ // 更新线段树的第k个值为val if(tr[i].l == k && tr[i].r == k)
{
tr[i].Max = val;
tr[i].Min = val;
tr[i].ne = ;
return;
}
push_down(i);
int mid = (tr[i].l + tr[i].r)/;
if(k <= mid)update(i<<,k,val);
else update((i<<)|,k,val);
push_up(i);
} void ne_update(int i,int l,int r){
if(tr[i].l==l&&tr[i].r==r){
tr[i].Max=-tr[i].Max;tr[i].Min=-tr[i].Min;
swap(tr[i].Max,tr[i].Min);
tr[i].ne^=;return;
}
push_down(i);
int mid=(tr[i].l+tr[i].r)>>;
if(r<=mid)ne_update(i<<,l,r);
else if(l>mid)ne_update((i<<)|,l,r);
else ne_update(i<<,l,mid),ne_update((i<<)|,mid+,r);
tr[i].Min=min(tr[i<<].Min,tr[(i<<)|].Min);
tr[i].Max=max(tr[i<<].Max,tr[(i<<)|].Max);
}
int query(int i,int l,int r){ //查询线段树中[l,r] 的最大值 if(tr[i].l == l && tr[i].r == r)
return tr[i].Max;
push_down(i);
int mid = (tr[i].l + tr[i].r)/;
if(r <= mid)return query(i<<,l,r);
else if(l > mid)return query((i<<)|,l,r);
else return max(query(i<<,l,mid),query((i<<)|,mid+,r));
push_up(i);
}
int findmax(int u,int v){//查询u->v边的最大值 int f1 = top[u], f2 = top[v];
int tmp = -;
while(f1 != f2)
{
if(deep[f1] < deep[f2])
{
swap(f1,f2);
swap(u,v);
}
tmp = max(tmp,query(,p[f1],p[u]));
u = fa[f1]; f1 = top[u];
}
if(u == v)return tmp;
if(deep[u] > deep[v]) swap(u,v);
return max(tmp,query(,p[son[u]],p[v]));
}
void Negate(int u,int v){
int f1=top[u],f2=top[v];
while(f1!=f2){
if(deep[f1]<deep[f2])swap(f1,f2),swap(u,v);
ne_update(,p[f1],p[u]);
u=fa[f1];f1=top[u];
}
if(u==v)return;
if(deep[u]>deep[v])swap(u,v);
ne_update(,p[son[u]],p[v]);
return;
}
int E[MAXN][];
int main()
{
//freopen("Cola.txt","r",stdin);
freopen("maintaintree.in","r",stdin);
freopen("maintaintree.out","w",stdout);
int T,n;
T=;
while(T--){
init();
scanf("%d",&n);
for(int i=;i<n-;i++){
scanf("%d%d%d",&E[i][],&E[i][],&E[i][]);
addedge(E[i][],E[i][]);
addedge(E[i][],E[i][]);
}
dfs1(,,);
dfs2(,);
build(,,pos-);
for(int i=;i<n-;i++){
if(deep[E[i][]]>deep[E[i][]])swap(E[i][],E[i][]);
update(,p[E[i][]],E[i][]);
}
char ch[];
int u,v;
while(){
scanf("%s",ch);
if(ch[]=='D')break;
scanf("%d%d",&u,&v);
if(ch[]=='Q')printf("%d\n",findmax(u,v));
else if(ch[]=='C')update(,p[E[u-][]],v);
else Negate(u,v);
}
}
return ;
}
cogs1583. [POJ3237]树的维护的更多相关文章
- Cogs 1583. [POJ3237]树的维护 LCT,树链剖分
题目:http://cojs.tk/cogs/problem/problem.php?pid=1583 1583. [POJ3237]树的维护 ★★★☆ 输入文件:maintaintree.in ...
- COGS 1583. [POJ3237]树的维护
二次联通门 : COGS 1583. [POJ3237]树的维护 /* COGS 1583. [POJ3237]树的维护 树链剖分 + 边权化点权 线段树 单点修改 + 区间取相反数 + 查询区间最大 ...
- 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 ...
- cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树
1583. [POJ 3237] 树的维护 ★★★★ 输入文件:maintaintree.in 输出文件:maintaintree.out 简单对比时间限制:5 s 内存限制:128 ...
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- CodeForces 587 E.Duff as a Queen 线段树动态维护区间线性基
https://codeforces.com/contest/587/problem/E 一个序列, 1区间异或操作 2查询区间子集异或种类数 题解 解题思路大同小异,都是利用异或的性质进行转化,st ...
随机推荐
- python3用pdfminer3k在线读取pdf文件
import importlib import sys import random from urllib.request import urlopen from urllib.request imp ...
- Flask中的内置session
Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪 1. Flask 中 session 是需要 secret_key 的 from ...
- ios点击链接直接跳转到 App Store 指定应用下载页面
//跳转到应用页面 NSString *str = [NSString stringWithFormat:@"http://itunes.apple.com/us/app/id%d&quo ...
- POJ1743 Musical Theme —— 后缀数组 重复出现且不重叠的最长子串
题目链接:https://vjudge.net/problem/POJ-1743 Musical Theme Time Limit: 1000MS Memory Limit: 30000K Tot ...
- <tx:advice/> 有关的设置
将描述通过 <tx:advice/> 标签来指定不同的事务性设置.默认的 <tx:advice/> 设置如下: 事务传播设置是 REQUIRED 隔离级别是 DEFAULT 事 ...
- python的模块导入问题
以下内容参考:http://www.xinxingjiaocheng.com/online/item/7/89 1.给模块起个别名 如果一个模块的名字很长很长,就像这样comput_the_value ...
- 设置document.domain实现js跨域注意点
转自:http://www.cnblogs.com/fsjohnhuang/archive/2011/12/07/2279554.html document.domain 用来得到当前网页的域名.比如 ...
- css:before和after中的content属性
css有一个属性叫做content.content只能使用在:after和:before之中.它用于在元素之前或者元素之后加上一些内容 就像这样: .email-address:before { co ...
- Java丨springMVC + Ajax 来进行分页
javaweb 分页技术 实现的方式有很多种,但是小编在网上问了度娘也问了谷老师,得到的答案让小编我不是很满意,so,还是自己写吧! 在小编的博文中,小编不会上传源码,只会把重要的代码和思路供大家参考 ...
- string类封装
class cMyString{ char* m_str; int m_strSize;public: cMyString();//指针指向一个空字符串 cMyString(char* str);// ...