题目链接

题意:树上更新某一点权值,更新两点简单路径权值,查询最大,最小,和

思路:思路应该比较简单,就是树链剖分后用线段树维护区间最大最小以及区间和。

但是本题比较特殊的是给的边权,转化为点权即可。但是查询或者更新两点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 [国家集训队]旅游 树链剖分相关推荐

  1. ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】

    题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...

  2. BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2157 是 hydro 的 BZOJ ...

  3. bzoj 3999: [TJOI2015]旅游(树链剖分)

    3999: [TJOI2015]旅游 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 423  Solved: 214 [Submit][Status ...

  4. 【树链剖分】旅游(luogu 3976)

    正题 luogu 3976 题目大意 给你一棵树,每个点有一个权值s 现在给你一条路径,让你选择两个点x,y,使y在x后面,且sy−sxs_y-s_xsy​−sx​最大 然后该路劲上所有点权值加v 解 ...

  5. 【BZOJ2157】旅游,树链剖分练习

    传送门 写在前面:模拟赛中CA爷卡我内存,暴力100变60--不过还是亲学长(毕竟在我初中的时候就是学长),每次做CA爷的题都是高分-- 思路: (迄今做的最爽的树链剖分) 被char哥带着做这道题, ...

  6. 【暖*墟】#树链剖分# 树链剖分学习与练习

    树链剖分 树链剖分是一种优化,将树上最常经过的几条链划为重点,用线段树来优化区间修改和查询. 并且因为在一棵子树中dfs序是连续的,并且在任意一条重链上,dfs序也是连续的, 可以认为轻链是单点修改, ...

  7. ACdream 1103 瑶瑶正式成为CEO(树链剖分+费用流)

    Problem Description 瑶瑶(tsyao)是某知名货运公司(顺丰)的老板,这个公司很大,货物运输量极大,因此公司修建了许多交通设施,掌控了一个国家的交通运输. 这个国家有n座城市,公司 ...

  8. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  9. 【bzoj1146】 [CTSC2008]网络管理Network【树链剖分+树套树+二分 线段树套Treap】

    1146: [CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公 ...

最新文章

  1. 这是我的第一个python程序怎么打-我的第一个Python程序
  2. Win10 通过cmd查看端口占用、相应进程、杀死进程等的命令
  3. 关于判断checkbox选中问题
  4. 最简单的Sublime插件开发教程
  5. 坚强生活(转)--To 小鱼,妹妹和傻女孩们
  6. 华北科技学院计算机期末考试,华北科技学院 专业计算机 考试专用
  7. paip.提升效率---提升绑定层次--form绑定取代field绑定
  8. layui内置loading等待加载
  9. c# getresponsestream返回byte[]_C#通过SharpZipLib库创建压缩文件
  10. SQL Server 中 with tmp 临时表的用法
  11. 树莓派(Raspberry Pi)搭建简单的lamp服务
  12. #leetcode刷题之路27-移除元素
  13. 基于springboot的鲜花商城系统
  14. 第一章 Android Framework 基础认知
  15. ACMer值得看的博客
  16. 产品读书《赋能:打造应对不确定性的敏捷团队》
  17. 新浪微博开放平台接口使用小结
  18. c语言背景音乐,背景图,背景字体
  19. 霍普菲尔得神经网络(Hopfield Neural Network)
  20. 妹妹,这回哥哥听你的了,以前哥哥真的太傻

热门文章

  1. python 的保留字
  2. RxJava repeat,repeatWhen,repeatUntil 的区别
  3. Please do not register multiple Pages in pages/buildhelp/buildhelp.js
  4. android支付宝调用
  5. shell getopts命令
  6. 深入理解Java虚拟机——第二章——Java内存区域与内存溢出异常
  7. Codeforces 903E Swapping Characters
  8. linux防火墙cc,Linux防火墙后面的Alljoyn服务(iptables)
  9. 给View 添加手势,点击无反应 如何给View添加点击事件,手势方法
  10. Docker - Install docker on CentOS