<题目链接>

题目大意:

给定一棵树,该树带有边权,现在对该树进行三种操作:

一:改变指定编号边的边权;

二:对树上指定路径的边权全部取反;

三:查询树上指定路径的最大边权值。

解题分析:

本题虽然只需要查询某段区间的最大值,但是线段树的每个节点都应该有最大和最小值,因为对区间取反之后,这段区间的最大值的相反数为最小值,最小值的相反数为最大值。然后就是注意对 lazy标记的操作。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define Lson l,mid,rt<<1
#define Rson mid+1,r,rt<<1|1
using namespace std;
const int M = 1e5+;
typedef long long ll;
#define INF 1e15
int T,n,pp;
int cnt,tot,head[M],p[M];
int sz[M],son[M],dep[M],f[M],top[M],rnk[M],id[M];
ll a[M];
char s[];
struct edge
{
int v,next;
ll w;
}e[M<<];
struct node
{
ll mx,mn;int lazy;
}tree[M<<];
void init(){
tot=cnt=;memset(head,-,sizeof(head));
}
void add(int u,int v,ll w){
e[++cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];
head[u]=cnt;
}
void fsd(int u,int fa){ //边权转化为点权
for(int i=head[u];~i;i=e[i].next){
int v=e[i].v;ll w=e[i].w;
if(v==fa) continue;
a[v]=w;p[(i-)/+]=v;
fsd(v,u);
}
}
void dfs(int u,int fa,int d){
sz[u]=;f[u]=fa;son[u]=-;dep[u]=d;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].v;
if(v==fa) continue;
dfs(v,u,d+);
sz[u]+=sz[v];
if(son[u]==-||sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs1(int u,int t){
id[u]=++tot;
rnk[tot]=u;
top[u]=t;
if(son[u]==-) return;
dfs1(son[u],t);
for(int i=head[u];~i;i=e[i].next){
int v=e[i].v;
if(v==f[u]||v==son[u]) continue;
dfs1(v,v);
}
}
void Pushup(int rt){ //维护该点的最大最小值
tree[rt].mx=max(tree[rt<<].mx,tree[rt<<|].mx);
tree[rt].mn=min(tree[rt<<].mn,tree[rt<<|].mn);
}
void Pushdown(int rt){
if(tree[rt].lazy){
int v=tree[rt].lazy;
tree[rt].lazy=;
if(v%==)return; //如果 lazy是偶数,那么就没必要 将lazy 下放,因为对区间进行偶数次取反,相当于没有进行操作 tree[rt<<].mn*=-;tree[rt<<].mx*=-; //将左,右子树的mn,mx取反
tree[rt<<|].mn*=-;tree[rt<<|].mx*=-; swap(tree[rt<<].mn,tree[rt<<].mx); //交换mx,mn
swap(tree[rt<<|].mx,tree[rt<<|].mn);
tree[rt<<].lazy+=v;tree[rt<<|].lazy+=v; //将父节点的lazy传递给子节点
}
}
void build(int l,int r,int rt){
tree[rt].mx=-INF,tree[rt].mn=INF;tree[rt].lazy=; //注意最大最小值都要记录,因为一旦取反,最小值就会变成最大值
if(l==r){
tree[rt].mx=tree[rt].mn=a[rnk[l]];
return;
}
int mid=(l+r)>>;
build(Lson);
build(Rson);
Pushup(rt);
}
void update(int L,int R,int l,int r,int rt){ //线段树上区间修改
if(L<=l&&r<=R){
tree[rt].lazy++; //这里来判断区间数值是否需要取是用 lazy%2 == 1 来判断的
tree[rt].mx*=-;tree[rt].mn*=-; //因为区间取反,所以mx和mn都 *-1
swap(tree[rt].mx,tree[rt].mn); //因为*-1,所以交换最大最小值
return ;
}
Pushdown(rt);
int mid=(l+r)>>;
if(L<=mid) update(L,R,Lson);
if(R>mid) update(L,R,Rson);
Pushup(rt);
}
void change(int l,int r,int rt,int loc,ll v){ //单点修改
if(l==r){
tree[rt].mx=tree[rt].mn=v; //将叶子节点的mx,mn都置为v
return;
}
Pushdown(rt);
int mid=(l+r)>>;
if(loc<=mid) change(Lson,loc,v);
else change(Rson,loc,v);
Pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){ //区间查询最大值
if(L<=l&&r<=R){
return tree[rt].mx;
}
Pushdown(rt);
int mid=(l+r)>>;
ll res=-INF;
if(L<=mid) res=max(res,query(L,R,Lson));
if(R>mid) res=max(res,query(L,R,Rson));
return res;
}
void updates(int x,int y){ //修改树上区间
int fx=top[x],fy=top[y];
while(fx!=fy){
if(dep[fx]>dep[fy]){
update(id[fx],id[x],,n,); //修改线段树上对应区间
x=f[fx],fx=top[x];
}
else{
update(id[fy],id[y],,n,);
y=f[fy],fy=top[y];
}
}
if(x==y) return;
if(dep[x]<dep[y])
update(id[son[x]],id[y],,n,);
else
update(id[son[y]],id[x],,n,);
}
ll sum(int x,int y){ //查询树上区间最大值
int fx=top[x],fy=top[y];ll res=-INF;
while(fx!=fy){
if(dep[fx]>dep[fy]){
res=max(res,query(id[fx],id[x],,n,));
x=f[fx],fx=top[x];
}
else{
res=max(res,query(id[fy],id[y],,n,));
y=f[fy],fy=top[y];
}
}
if(x==y) return res;
if(dep[x]<dep[y])
res=max(res,query(id[son[x]],id[y],,n,));
else
res=max(res,query(id[son[y]],id[x],,n,));
return res;
} int main(){
scanf("%d",&T);
while(T--){
init();
scanf("%d",&n);
for(int i=;i<n;i++){
int u,v;ll w;
scanf("%d%d%lld",&u,&v,&w);
add(u,v,w);add(v,u,w);
} fsd(,-);a[]=;
dfs(,-,);
dfs1(,);
build(,n,);
while(true){
scanf("%s",s);
if(s[]=='D') break;
if(s[]=='C'){
int a;ll b;
scanf("%d%lld",&a,&b); //单点修改
change(,n,,id[p[a]],b); //线段树上单点修改
}
if(s[]=='N'){
int a,b;
scanf("%d%d",&a,&b);
updates(a,b); //对树上的区间进行修改
}
if(s[]=='Q'){
int a,b;
scanf("%d%d",&a,&b);
printf("%lld\n",sum(a,b)); //对树上的区间查询
}
}
}
return ;
}

  

2018-09-11

POJ 3237 Tree 【树链剖分】+【线段树】的更多相关文章

  1. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

  2. 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 ...

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

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

  4. POJ3237 Tree 树链剖分 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...

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

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

  6. 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, ...

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

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

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

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

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

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

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

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

随机推荐

  1. hdu1198 普通的并查集

    今天开始(第三轮)并查集,,之前学的忘了一些 本题很简单直接上代码 #include<iostream> #include<cstring> #include<cstdi ...

  2. Java 单字节、多字节读取文本文档中的内容

    文本文档位于工程下. 鼠标右击工程,选择“new - File”,即可创建. 文本文档的格式:GBK 单字节读取 import java.io.File; import java.io.FileInp ...

  3. MySQL5.7版本及以上,改密码sql语句;grant创建用户已经密码

    mysql> update mysql.user set authentication_string = password('*****')  where user = 'root'; gran ...

  4. jQuery常见的几个文档处理方式

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  5. easyui实现背景图片半透明状态,悬浮在大背景之上

    首先是查找素材,使用AI将所需要的图案画出来,切记将图案的背景设置为所需要的透明状态.项目使用的是easyui架构 为啥加两个背景图呢,因为这样的布局最开始是给一个矩形框加上的背景图片,若是还使用矩形 ...

  6. unicode解码

    var newStr = System.Text.RegularExpressions.Regex.Unescape(str);

  7. gulp构建自动化项目

    'use strict'; var gulp = require('gulp'), browserSync = require('browser-sync').create(), SSI = requ ...

  8. 将Elasticsearch的快照备份到HDFS

    1.安装Elasticsearch插件repository-hdfs 下载地址:https://artifacts.elastic.co/downloads/elasticsearch-plugins ...

  9. Git坑换行符自动转换 [转载]

    转自https://www.cnblogs.com/zjoch/p/5400251.html 源起 一直想在 GitHub 上发布项目.参与项目,但 Git 这货比较难学啊.买了一本<Git 权 ...

  10. EF连接MySql数据库

    Windows要想EF连接MySql,首先要安装两个应用程序 mysql-connector-net-6.8.8.msimysql-for-visualstudio-1.2.7.msi 项目还需要两个 ...