POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-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 树链剖分 线段树的更多相关文章
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- 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 ...
- 【CF725G】Messages on a Tree 树链剖分+线段树
[CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...
- 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, ...
- Water Tree CodeForces 343D 树链剖分+线段树
Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- B20J_3231_[SDOI2014]旅行_树链剖分+线段树
B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
随机推荐
- 八、IIC 接口
8.1 IIC接口介绍 8.1.1 IIC 总线的概念 I2C总线是由Philips公司开发的一种简单.双向二线制同步串行总线.它只需要两根线即可在连接于总线上的器件之间传送信息. 主器件用于启动总线 ...
- setTimeout设置不起作用
setTimeout立刻调用了 a()方法而不是xx秒以后,是因为调用方法时候没有加双引号. 正确做法:setTimeout(" a() ",5000): 调用 a() 方法时候要 ...
- luogu P2123 皇后游戏
传送门 跟国王游戏一样的分析 考虑相邻的两个大臣,设他们前面的\(\sum a_j\)为\(s\),同时注意到后面人的贡献更大 所以\(i\)在前面时,\(c_j=\max(\max(c_{last} ...
- django(一)验证码
这里讲讲在django中使用第三方插件验证码的流程. 一. 先安装pillow, 通过 python -m pip install pillow 二.安装完后,在官方网站上看操作过程.地址:pillo ...
- JavaScript练习 - 正反选练习
正反选练习 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- 前端 - Ajax (1)
Ajax 主要作用 用于隐式提交,有别于input 提交时不会跳转/刷新页面. 前端: html 代码:(id) <p> <input id="user" typ ...
- 文件&报表状态ID
def_filestatus Uploading=4 WaitingParse=6 Parsing=10 Completed=14 ParseError=1006 UploadError=1004 d ...
- jdk8系列一、jdk8 Lamda表达式语法、接口的默认方法和静态方法、supplier用法
一.简介 毫无疑问,Java 8是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和JVM等方面的十多个新特性. 在本文中我们将学习这些新特性,并用实际 ...
- 调用链系列二、Zipkin 和 Brave 实现(springmvc、RestTemplate)服务调用跟踪
Brave介绍 1.Brave简介 Brave 是用来装备 Java 程序的类库,提供了面向标准Servlet.Spring MVC.Http Client.JAX RS.Jersey.Resteas ...
- MyEclipse中将项目的编码从默认GBK改变为默认UTF-8