POJ 3237 Tree 【树链剖分】+【线段树】
<题目链接>
题目大意:
给定一棵树,该树带有边权,现在对该树进行三种操作:
一:改变指定编号边的边权;
二:对树上指定路径的边权全部取反;
三:查询树上指定路径的最大边权值。
解题分析:
本题虽然只需要查询某段区间的最大值,但是线段树的每个节点都应该有最大和最小值,因为对区间取反之后,这段区间的最大值的相反数为最小值,最小值的相反数为最大值。然后就是注意对 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 【树链剖分】+【线段树】的更多相关文章
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- 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 ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- 【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 ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- B20J_3231_[SDOI2014]旅行_树链剖分+线段树
B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...
随机推荐
- Confluence 6 访问日志脚本
日志访问脚本在连接:https://confluence.atlassian.com/download/attachments/133267635/Atlassian-accessLogScripts ...
- 【python】mongo删除数据
参考:https://stackoverflow.com/questions/23334743/setting-justone-limiter-for-pymongo-remove-throws-ty ...
- ERROR 1044 (42000): Access denied for user 'root'@'%' to database 'mysql'
原因:修改数据库账号时删除了默认的localhost root, 新建了% root 但没有赋予全部权限; 解决方法: 1.关闭数据库# mysqld stop 2.在my.cnf里加入skip-g ...
- laravel 注入那点事
public function delete(Group $groupId, Post $postId) { $postId->delete(); return response()->j ...
- laravel 队列发送邮件
批量处理任务的场景在我们开发中是经常使用的,比如邮件群发,消息通知,短信,秒杀等等,我们需要将这个耗时的操作放在队列中来处理,从而大幅度缩短Web请求和相应的时间.下面讲解下Laravel中队列的使用 ...
- js中json对象数组按对象属性排序---1
转载:https://www.cnblogs.com/jasonwang2y60/p/6656103.html 在实际工作经常会出现这样一个问题:后台返回一个数组中有i个json数据,需要我们根据js ...
- 沈阳润才教育CRM
一.CRM初始 CRM,客户关系管理系统(Customer Relationship Management).企业用CRM技术来管理与客户之间的关系,以求提升企业成功的管理方式,其目的是协助企业管理销 ...
- scss文件使用笔记
1.编写兼容性代码 例如透明度,兼容IE @mixin mOpacity($o){ opacity:$o/100; filter:alpha(opacity=$o); } //引用 .box{ @in ...
- 字典树HihoCoder - 1014
输入的第一行为一个正整数n,表示词典的大小,其后n行,每一行一个单词(不保证是英文单词,也有可能是火星文单词哦),单词由不超过10个的小写英文字母组成,可能存在相同的单词,此时应将其视作不同的单词.接 ...
- mybatis 遍历map;
mybatis 遍历map; 参考http://blog.csdn.net/hj7jay/article/details/78652050 ps: ${m[key]}这是显示 打印的key读value ...