P1505 [国家集训队]旅游 树链剖分
题目链接
题意:树上更新某一点权值,更新两点简单路径权值,查询最大,最小,和
思路:思路应该比较简单,就是树链剖分后用线段树维护区间最大最小以及区间和。
但是本题比较特殊的是给的边权,转化为点权即可。但是查询或者更新两点x,y之间路径的时候,x,y的lca点的点权对应的边是
fathar[lca]--->lca这条边,不属于x->y的简单路径。
所以在更新或者查询的时候,当处理到x,y属于同一条链的时候
这个过程说的是查询x->y,x,y一直往上跳,直到有一个跳到lca时(若dep[x]<dep[y],x就是lca)
这时x,y属于一个连续区间,又因x点的权值不算,就是更新(dfn[x]+1,y),dfn为时间戳
所以算是一道比较基础的树链剖分吧。
但是,这该死的码量,也太恶心了,我就写了一个bug,找了整两个小时?,wc
一个update1写成update我就真找不到。。。我太难了
//#pragma comment (linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#include<list>
#include<time.h>
#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define lowbit(x) x&(-x)
#define min4(a, b, c, d) min(min(a,b),min(c,d))
#define min3(x, y, z) min(min(x,y),z)
#define max3(x, y, z) max(max(x,y),z)
#define max4(a, b, c, d) max(max(a,b),max(c,d))
#define pii make_pair
#define pr pair<int,int>
//freopen("E://1.in","r",stdin);
//freopen("E://1.out","w",stdout);
typedef unsigned long long ull;
typedef long long ll;
const int inff = 0x3f3f3f3f;
const long long inFF = 9223372036854775807;
const int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
const int mdir[8][2] = {0, 1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 1, -1, -1, -1};
const double eps = 1e-10;
const double PI = acos(-1.0);
const double E = 2.718281828459;
using namespace std;
//const int mod=1e9+7;
const int maxn=2e5+5;
int d[maxn],f[maxn],dfn[maxn],tim[maxn],top[maxn],size[maxn],son[maxn],a[maxn];
int head[maxn],sign;
char s[3];
struct node
{int to,p,val;
}edge[maxn<<1];
struct nod
{int mx,mi,sum;
}tree[maxn<<2];
int lazy[maxn<<2];
int n,t;
void init()
{for(int i=0;i<=n;i++) head[i]=-1;sign=t=0;
}
void add(int u,int v,int val)
{edge[sign]=node{v,head[u],val};head[u]=sign++;
}
void dfs1(int u,int pre,int step)
{d[u]=step;f[u]=pre;size[u]=1;for(int i=head[u];~i;i=edge[i].p){int v=edge[i].to;if(v==pre) continue;a[v]=edge[i].val;dfs1(v,u,step+1);size[u]+=size[v];if(size[v]>size[son[u]]) son[u]=v;}
}
void dfs2(int u,int tp)
{dfn[u]=++t;tim[t]=u;top[u]=tp;if(son[u]) dfs2(son[u],tp);for(int i=head[u];~i;i=edge[i].p){int v=edge[i].to;if(v!=f[u]&&v!=son[u]) dfs2(v,v);}
}
void pushup(int i,int l,int r)
{tree[i].sum=tree[lson].sum+tree[rson].sum;tree[i].mx=max(tree[lson].mx,tree[rson].mx);tree[i].mi=min(tree[lson].mi,tree[rson].mi);
}
void pushdown(int i,int l,int r)
{if(lazy[i]){tree[lson].sum=-tree[lson].sum;tree[rson].sum=-tree[rson].sum;int t1=tree[lson].mx,t2=tree[rson].mx,s1=tree[lson].mi,s2=tree[rson].mi;tree[lson].mx=-s1,tree[rson].mx=-s2,tree[lson].mi=-t1,tree[rson].mi=-t2;lazy[lson]^=1;lazy[rson]^=1;lazy[i]=0;}
}
void build(int i,int l,int r)
{if(l==r){tree[i].sum=tree[i].mi=tree[i].mx=a[tim[l]];return ;}int mid=half;build(Lson);build(Rson);pushup(myself);
}
void update(int i,int l,int r,int x,int val)//单点更新
{if(l==r){tree[i].sum=tree[i].mi=tree[i].mx=val;return;}int mid=half;pushdown(myself);if(x<=mid) update(Lson,x,val);else update(Rson,x,val);pushup(myself);
}
void update1(int i,int l,int r,int ql,int qr)//区间取反
{if(ql>qr) return;if(ql<=l&&qr>=r){tree[i].sum=-tree[i].sum;lazy[i]=1-lazy[i];int x=tree[i].mi;tree[i].mi=-tree[i].mx;tree[i].mx=-x;return;}pushdown(myself);int mid=half;if(qr<=mid) update1(Lson,ql,qr);else if(ql>mid) update1(Rson,ql,qr);else update1(Lson,ql,mid),update1(Rson,mid+1,qr);pushup(myself);
}int find_sum(int i,int l,int r,int ql,int qr)
{if(ql>qr) return 0;if(ql<=l&&qr>=r) return tree[i].sum;pushdown(myself);int mid=half;if(qr<=mid) return find_sum(Lson,ql,qr);else if(ql>mid) return find_sum(Rson,ql,qr);else return find_sum(Lson,ql,mid)+find_sum(Rson,mid+1,qr);
}
int find_max(int i,int l,int r,int ql,int qr)
{if(ql>qr) return -inff;if(ql<=l&&qr>=r) return tree[i].mx;pushdown(myself);int mid=half;if(qr<=mid) return find_max(Lson,ql,qr);else if(ql>mid) return find_max(Rson,ql,qr);else return max(find_max(Lson,ql,mid),find_max(Rson,mid+1,qr));
}
int find_min(int i,int l,int r,int ql,int qr)
{if(ql>qr) return inff;if(ql<=l&&qr>=r) return tree[i].mi;pushdown(myself);int mid=half;if(qr<=mid) return find_min(Lson,ql,qr);else if(ql>mid) return find_min(Rson,ql,qr);else return min(find_min(Lson,ql,mid),find_min(Rson,mid+1,qr));
}
void solve(int x,int y)//区间更新pre处理
{while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]) swap(x,y);update1(1,1,n,dfn[top[x]],dfn[x]);x=f[top[x]];}if(d[x]>d[y]) swap(x,y);update1(1,1,t,dfn[x]+1,dfn[y]);
}
int get_max(int x,int y)
{int ans=-inff;while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]) swap(x,y);ans=max(ans,find_max(1,1,t,dfn[top[x]],dfn[x]));x=f[top[x]];}if(d[x]>d[y]) swap(x,y);ans=max(ans,find_max(1,1,t,dfn[x]+1,dfn[y]));return ans;}
int get_min(int x,int y)
{int ans=inff;while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]) swap(x,y);ans=min(ans,find_min(1,1,t,dfn[top[x]],dfn[x]));x=f[top[x]];}if(d[x]>d[y]) swap(x,y);ans=min(ans,find_min(1,1,t,dfn[x]+1,dfn[y]));return ans;
}
int get_sum(int x,int y)
{int ans=0;while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]) swap(x,y);ans+=find_sum(1,1,t,dfn[top[x]],dfn[x]);x=f[top[x]];}if(d[x]>d[y]) swap(x,y);ans+=find_sum(1,1,t,dfn[x]+1,dfn[y]);return ans;
}
int main()
{
// freopen("E://2.in","r",stdin);
// freopen("E://1.out","w",stdout);cin>>n;int x,y,val;init();for(int i=1;i<n;i++){scanf("%d %d %d",&x,&y,&val);x++,y++;add(x,y,val),add(y,x,val);}dfs1(1,1,1);dfs2(1,1);build(1,1,n);int r;cin>>r;while(r--){scanf("%s",s);scanf("%d %d",&x,&y);x++,y++;if(s[0]=='C') update(1,1,n,dfn[x],y-1);else if(s[0]=='N') solve(x,y);else if(s[2]=='M') printf("%d\n",get_sum(x,y));else if(s[2]=='X') printf("%d\n",get_max(x,y));else printf("%d\n",get_min(x,y));}return 0;
}
P1505 [国家集训队]旅游 树链剖分相关推荐
- ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】
题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...
- BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)【BZOJ计划】
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2157 是 hydro 的 BZOJ ...
- bzoj 3999: [TJOI2015]旅游(树链剖分)
3999: [TJOI2015]旅游 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 423 Solved: 214 [Submit][Status ...
- 【树链剖分】旅游(luogu 3976)
正题 luogu 3976 题目大意 给你一棵树,每个点有一个权值s 现在给你一条路径,让你选择两个点x,y,使y在x后面,且sy−sxs_y-s_xsy−sx最大 然后该路劲上所有点权值加v 解 ...
- 【BZOJ2157】旅游,树链剖分练习
传送门 写在前面:模拟赛中CA爷卡我内存,暴力100变60--不过还是亲学长(毕竟在我初中的时候就是学长),每次做CA爷的题都是高分-- 思路: (迄今做的最爽的树链剖分) 被char哥带着做这道题, ...
- 【暖*墟】#树链剖分# 树链剖分学习与练习
树链剖分 树链剖分是一种优化,将树上最常经过的几条链划为重点,用线段树来优化区间修改和查询. 并且因为在一棵子树中dfs序是连续的,并且在任意一条重链上,dfs序也是连续的, 可以认为轻链是单点修改, ...
- ACdream 1103 瑶瑶正式成为CEO(树链剖分+费用流)
Problem Description 瑶瑶(tsyao)是某知名货运公司(顺丰)的老板,这个公司很大,货物运输量极大,因此公司修建了许多交通设施,掌控了一个国家的交通运输. 这个国家有n座城市,公司 ...
- BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )
树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...
- 【bzoj1146】 [CTSC2008]网络管理Network【树链剖分+树套树+二分 线段树套Treap】
1146: [CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公 ...
最新文章
- 这是我的第一个python程序怎么打-我的第一个Python程序
- Win10 通过cmd查看端口占用、相应进程、杀死进程等的命令
- 关于判断checkbox选中问题
- 最简单的Sublime插件开发教程
- 坚强生活(转)--To 小鱼,妹妹和傻女孩们
- 华北科技学院计算机期末考试,华北科技学院 专业计算机 考试专用
- paip.提升效率---提升绑定层次--form绑定取代field绑定
- layui内置loading等待加载
- c# getresponsestream返回byte[]_C#通过SharpZipLib库创建压缩文件
- SQL Server 中 with tmp 临时表的用法
- 树莓派(Raspberry Pi)搭建简单的lamp服务
- #leetcode刷题之路27-移除元素
- 基于springboot的鲜花商城系统
- 第一章 Android Framework 基础认知
- ACMer值得看的博客
- 产品读书《赋能:打造应对不确定性的敏捷团队》
- 新浪微博开放平台接口使用小结
- c语言背景音乐,背景图,背景字体
- 霍普菲尔得神经网络(Hopfield Neural Network)
- 妹妹,这回哥哥听你的了,以前哥哥真的太傻
热门文章
- python 的保留字
- RxJava repeat,repeatWhen,repeatUntil 的区别
- Please do not register multiple Pages in pages/buildhelp/buildhelp.js
- android支付宝调用
- shell getopts命令
- 深入理解Java虚拟机——第二章——Java内存区域与内存溢出异常
- Codeforces 903E Swapping Characters
- linux防火墙cc,Linux防火墙后面的Alljoyn服务(iptables)
- 给View 添加手势,点击无反应 如何给View添加点击事件,手势方法
- Docker - Install docker on CentOS