欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - POJ3237


题意概括

Description

给你由N个结点组成的树。树的节点被编号为1到N,边被编号为1到N-1。每一条边有一个权值。然后你要在树上执行一系列指令。指令可以是如下三种之一:
CHANGE i v:将第i条边的权值改成v。
NEGATE a b:将点a到点b路径上所有边的权值变成其相反数。
QUERY a b:找出点a到点b路径上各边的最大权值。

Input
多组数据,数据为T<=20,对于每组数据:
第一行有一个整数N(N<=10000)。
接下来N-1行每行有三个整数a,b,c,代表点a和点b之间有一条权值为c的边。这些边按照其编号从小到大给出。
接下来是若干条指令(不超过10^5条),都按照上面所说的格式。
最后一行是"DONE".

Output
对每个“QUERY”指令,输出一行,即路径上各边的最大权值。

Sample Input
1
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output
1
3


题解

  树链剖分+线段树单点修改、区间修改、区间询问。

  对于取相反数的,我们只需要维护一个最大值,一个最小值,然后打一下懒标记就可以了。

  在下传的时候,最大值反一反一定是最小的,最小值反一反一定是最大的,然后就好办了。


代码

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int N=10005;
struct Edge{
int cnt,y[N*2],z[N*2],nxt[N*2],fst[N];
void clear(){
cnt=0;
memset(fst,0,sizeof fst);
}
void add(int a,int b,int c){
y[++cnt]=b,z[cnt]=c,nxt[cnt]=fst[a],fst[a]=cnt;
}
}g;
struct edge{
int a,b,c;
}e[N];
int T,n,fa[N],size[N],fadis[N],depth[N],son[N],top[N],p[N],ap[N],cnp;
struct Tree{
int ma,mi,add;
}t[N*4];
void Get_Gen_Info(int rt,int pre,int d){
depth[rt]=d,fa[rt]=pre,size[rt]=1,son[rt]=-1;
for (int i=g.fst[rt];i;i=g.nxt[i])
if (g.y[i]!=pre){
int s=g.y[i];
Get_Gen_Info(s,rt,d+1);
fadis[s]=g.z[i];
size[rt]+=size[s];
if (son[rt]==-1||size[s]>size[son[rt]])
son[rt]=s;
}
}
void Get_Pos(int rt,int tp){
top[rt]=tp,p[rt]=++cnp,ap[cnp]=rt;
if (son[rt]==-1)
return;
else
Get_Pos(son[rt],tp);
for (int i=g.fst[rt];i;i=g.nxt[i]){
int s=g.y[i];
if (s!=fa[rt]&&s!=son[rt])
Get_Pos(s,s);
}
}
void pushup(int rt){
int ls=rt<<1,rs=ls|1;
t[rt].mi=min(t[ls].mi,t[rs].mi);
t[rt].ma=max(t[ls].ma,t[rs].ma);
}
void build(int rt,int le,int ri){
t[rt].add=0;
if (le==ri){
t[rt].ma=t[rt].mi=fadis[ap[le]];
return;
}
int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
build(ls,le,mid);
build(rs,mid+1,ri);
pushup(rt);
}
void fz(int &x,int &y){
x=-x,y=-y;
swap(x,y);
}
void pushdown(int rt){
int &a=t[rt].add;
int ls=rt<<1,rs=ls|1;
if (a==0)
return;
t[ls].add^=1,t[rs].add^=1;
fz(t[ls].ma,t[ls].mi);
fz(t[rs].ma,t[rs].mi);
a=0;
}
void change(int rt,int le,int ri,int pos,int v){
if (le==ri){
t[rt].mi=t[rt].ma=v;
return;
}
pushdown(rt);
int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
if (pos<=mid)
change(ls,le,mid,pos,v);
else
change(rs,mid+1,ri,pos,v);
pushup(rt);
}
void update(int rt,int le,int ri,int xle,int xri){
if (le>xri||ri<xle)
return;
if (xle<=le&&ri<=xri){
t[rt].add^=1;
fz(t[rt].ma,t[rt].mi);
return;
}
pushdown(rt);
int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
update(ls,le,mid,xle,xri);
update(rs,mid+1,ri,xle,xri);
pushup(rt);
}
int query(int rt,int le,int ri,int xle,int xri){
if (le>xri||ri<xle)
return -1e9;
if (xle<=le&&ri<=xri)
return t[rt].ma;
pushdown(rt);
int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
return max(query(ls,le,mid,xle,xri),query(rs,mid+1,ri,xle,xri));
}
void fupdate(int a,int b){
int f1=top[a],f2=top[b];
while (f1!=f2){
if (depth[f1]<depth[f2])
swap(f1,f2),swap(a,b);
update(1,1,n,p[f1],p[a]);
a=fa[f1],f1=top[a];
}
if (a==b)
return;
if (depth[a]>depth[b])
swap(a,b);
update(1,1,n,p[son[a]],p[b]);
}
int find(int a,int b){
int f1=top[a],f2=top[b],ans=-1e9;
while (f1!=f2){
if (depth[f1]<depth[f2])
swap(f1,f2),swap(a,b);
ans=max(ans,query(1,1,n,p[f1],p[a]));
a=fa[f1],f1=top[a];
}
if (a==b)
return ans;
if (depth[a]>depth[b])
swap(a,b);
return max(ans,query(1,1,n,p[son[a]],p[b]));
}
int main(){
scanf("%d",&T);
while (T--){
scanf("%d",&n);
g.clear();
for (int i=1,a,b,c;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
g.add(a,b,c);
g.add(b,a,c);
e[i].a=a,e[i].b=b,e[i].c=c;
}
cnp=0,fadis[1]=0;
Get_Gen_Info(1,0,0);
Get_Pos(1,1);
build(1,1,n);
for (int i=1;i<n;i++)
if (depth[e[i].a]>depth[e[i].b])
swap(e[i].a,e[i].b);
char str[10];
int a,b;
while (scanf("%s",str)&&str[0]!='D'){
scanf("%d%d",&a,&b);
if (str[0]=='C')
change(1,1,n,p[e[a].b],b);
else if (str[0]=='N')
fupdate(a,b);
else
printf("%d\n",find(a,b));
}
}
return 0;
}

  

POJ3237 Tree 树链剖分 线段树的更多相关文章

  1. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  2. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  3. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  4. 【CF725G】Messages on a Tree 树链剖分+线段树

    [CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...

  5. Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  6. Water Tree CodeForces 343D 树链剖分+线段树

    Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...

  7. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  8. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

  9. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

随机推荐

  1. 编写优秀jQuery插件技巧

    1. 把你的代码全部放在闭包里面 这是我用的最多的一条.但是有时候在闭包外面的方法会不能调用. 不过你的插件的代码只为你自己的插件服务,所以不存在这个问题,你可以把所有的代码都放在闭包里面. 而方法可 ...

  2. C++ 中 #ifndef, #define, #endif 宏定义

    目的:为了保证包含的内容只被程序(include) 和编译了一次.判断预处理器常量是否已被定义. 预编译将所有头文件(#include"XXX.h")用头文件中的内容来替换,头文件 ...

  3. MySQL 之 数据库自动生成ID格式化编号(字符串格式化填充/拼接/时间)

    # 用户账号:1-4位:入职年份:5-6位:入职月份:7-11位:员工入职顺序号 select concat( date_format(now(),'%Y'), date_format(now(),' ...

  4. js给<img>的src赋值

    用js原生方法:document.getElementById("imageId").src = "xxxx.jpg";用Jquery方法:$("#i ...

  5. android 使用SQLite存储数据

    创建一个类继承SQLiteOpenHelper,重写他的构造方法.onCreate().onUpgrade() 构建出SQLiteOpenHelper实例后,再调用他的getReadableDatab ...

  6. 【windows核心编程】系统消息与自定义钩子(Hook)使用

    一.HOOk Hook是程序设计中最为灵活多变的技巧之一,在windows下,Hook有两种含义: 1.系统提供的消息Hook机制 2.自定义的Hook编程技巧 其中,由系统提供的消息钩子机制是由一系 ...

  7. DMA及cache一致性的学习心得 --dma_alloc_writecombine【转】

    转自:https://www.cnblogs.com/hoys/archive/2012/02/17/2355914.html 来源:http://xmxohy.blog.163.com/blog/s ...

  8. Python3学习笔记23-StringIO和BytesIO

    StringIO 很多时候数据读取不一定是文件,也可以在内存中 StringIO顾名思义就是在内存中读写str 要把str写入StringIO,我们需要先创建一个StringIO,然后像文件一样写入即 ...

  9. centos7.2环境编译安装mysql5.5.48

    一.安装cmake编译工具 跨平台编译器 查看是否已经安装了gcc # rpm -qa | grep gcc # yum install -y gcc-c++ # yum install -y cma ...

  10. win7 X64系统上 PL/SQL不能识别Oracle实例

    电脑系统为Win7 64位,安装的PLSql为64位,安装的Oracle客户端为运行时类型的,应该为32位客户端 电脑上之前安装的32位toad可以识别Oracle实例 在系统添加了oracle_ho ...