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 :把某个节点 ...
随机推荐
- castle动态代理的使用
转自:https://blog.csdn.net/educast/article/details/6565447#动态代理的原理 原理其实很简单,就是在运行时生成新的对象,姑且叫做T,并使T继承自需要 ...
- 20155333 2016-2017-2 《Java程序设计》第六周学习总结
20155333 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 流(Stream)是对「输入输出」的抽象,注意「输入输出」是相对程序而言的 InputStr ...
- Anaconda的安装和更新
下载地址官网:https://www.anaconda.com/distribution/ 一.安装 二.下载安装完成后我们来检验一下是否安装成功 点击“开始” —— “Anaconda3(64-bi ...
- QWidget窗口类
import sys from PyQt5.QtWidgets import QWidget, QApplication,QPushButton from PyQt5.QtGui import QIc ...
- dubbo集群服务下一台服务挂了对服务调用的影响
一.问题描述:项目中2台dubbo服务给移动端提供查询接口,移动端反应说查询时而很快(秒刷),时而很慢(4-5秒). 二.问题分析: 1.问题猜想:网络不稳定原因导致,但是切换公司wifi和手机4G, ...
- 错误RSA host key for [ip address] has changed and you have requested strict checking.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING: REMOTE HOST IDENTIFICATION HAS ...
- Database学习 - mysql 数据库 数据操作
mysql数据操作 查询语法 select * | field1,field1 ... from 表名 where 条件 group by 字段 having 筛选 order by 字段 limit ...
- Android常用网络请求框架Volley Retrofit (okHttp)
Android系统中主要提供了两种方式来进行HTTP通信,HttpURLConnection和HttpClient.在 Android 5.0 的时候 Google 就不推荐使用 HttpClient ...
- Junit的Assert用法
package junit.framework; /** * A set of assert methods. Messages are only displayed when an assert f ...
- 【python图像处理】图像的缩放、旋转与翻转
[python图像处理]图像的缩放.旋转与翻转 图像的几何变换,如缩放.旋转和翻转等,在图像处理中扮演着重要的角色,python中的Image类分别提供了这些操作的接口函数,下面进行逐一介绍. 1.图 ...