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上原题略有不同。

【来源】

POJ 3237 Tree

难点在于取相反数操作

记录下最大值和最小值,有取相反数操作时,就把两个值变成相反数,再交换两数的值就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]树的维护的更多相关文章

  1. Cogs 1583. [POJ3237]树的维护 LCT,树链剖分

    题目:http://cojs.tk/cogs/problem/problem.php?pid=1583 1583. [POJ3237]树的维护 ★★★☆   输入文件:maintaintree.in  ...

  2. COGS 1583. [POJ3237]树的维护

    二次联通门 : COGS 1583. [POJ3237]树的维护 /* COGS 1583. [POJ3237]树的维护 树链剖分 + 边权化点权 线段树 单点修改 + 区间取相反数 + 查询区间最大 ...

  3. poj3237 树链部分 边权模板

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7384   Accepted: 2001 Description ...

  4. 【bzoj3533】[Sdoi2014]向量集 线段树+STL-vector维护凸包

    题目描述 维护一个向量集合,在线支持以下操作:"A x y (|x|,|y| < =10^8)":加入向量(x,y);"Q x y l r (|x|,|y| < ...

  5. hdu 1556 Color the ball(线段树区间维护+单点求值)

    传送门:Color the ball Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/3276 ...

  6. cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树

    1583. [POJ 3237] 树的维护 ★★★★   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比时间限制:5 s   内存限制:128 ...

  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. CentOS下配置静态IP

    第一.在VMware中进行配置使用桥接的方式.点击编辑选择虚拟网络编辑器 选择桥接模式,选择桥接到外部的网卡.选择我们主机下的网卡 第二步.配置虚拟机使用桥接模式 第三步:启动虚拟机进入到 /etc/ ...

  2. 什么是XXX

    1.什么事框架 框架式一组程序的集合,包含了一系列的最佳实践,作用是  解决某个领域的问题. 当我们使用某个框架时,其实是把一系列JAR包加载到CLASSPATH路径中,实际上是获得了JAR中所有对J ...

  3. <密码学入门>关于RSA算法的加密解密及代码实现

    RSA算法 是一种公钥加密算法,RSA算法相比别的算法思路非常清晰,但是想要破解的难度非常大.RSA算法基于一个非常简单的数论事实:两个素数相乘得到一个大数很容易,但是由一个大数分解为两个素数相乘却非 ...

  4. Spring 4.3 的新功能和增强

    转载自https://my.oschina.net/waylau/blog/698186 核心容器改进 核心容器额外提供了更丰富的元数据来改进编程. 默认 Java 8 的方法检测为 bean 属性的 ...

  5. oracle删除重复数据只保留一条

    -- 如表role_user的数据 ROLEID USERID -- 删除相同记录只剩下一条记录 根据两个字段查询重复数据 (roleid,userid) ) 删除重复数据只保留一条 delete f ...

  6. 揭秘FaceBook Puma演变及发展——FaceBook公司的实时数据分析平台是建立在Hadoop 和Hive的基础之上,这个根能立稳吗?hive又是sql的Map reduce任务拆分,底层还是依赖hbase和hdfs存储

    在12月2日下午的“大数据技术与应用”分论坛的第一场演讲中,来自全球知名互联网公司——FaceBook公司的软件工程师.研发经理邵铮就带来了一颗重磅炸弹,他将为我们讲解FaceBook公司的实时数据处 ...

  7. python基础-发邮件smtp

    先来想下发送邮件需要填写什么,还需要有什么条件1.与邮件服务器建立连接,用户名和密码2.发邮件:发件人,收件人,主题,内容,附件3.发送 使用第三方邮箱发送邮件 #! /usr/bin/env pyt ...

  8. 如何在u盘上安装系统, (非安装盘)

    在u盘中永久安装Fedora. 需要两个u盘(live usb), 一个系统镜像文件. 方法是: 用一个u盘作安装盘,  然后通过这个u盘把系统安装到另一个u盘上. 两个U盘上的文件都会被覆盖. 1. ...

  9. [acm]HDOJ 3082 Simplify The Circuit

    题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3082 字符串处理+并联电阻公式 //11481261 2014-08-18 16:52:47 Acc ...

  10. ACM学习历程—HDU 4287 Intelligent IME(字典树 || map)

    Description We all use cell phone today. And we must be familiar with the intelligent English input ...