传送门
写在前面:模拟赛中CA爷卡我内存,暴力100变60……不过还是亲学长(毕竟在我初中的时候就是学长),每次做CA爷的题都是高分……
思路:
(迄今做的最爽的树链剖分)
被char哥带着做这道题,结果耗了好久时间调好,这应该是第一次写边链剖了?与点链剖不同的是要处理下边(深度大的变成入点),然后建树时,这个入点的权值就是边的权值(根的权值为0)。查询时,最后l,r到同一条链上来,要让l赋为l的重儿子,然后再求值(如果l,r是同一个点就直接退出,不用赋值重儿子了,因为相同的点之间没有路径权值)
其他就是简单的加标记求最大最小与总和了,这个题多一步取反操作,直接打标记,最大值最小值交换,然后最大最小与总和全部取相反数就行了
注意:读入判断命令要注意……
代码:

#include<bits/stdc++.h>
#define Inf 0x7fffffff
using namespace std;
int n,m,tot,cnt;
char ch;
int val[20010],L[20010],first[20010],pre[20010],dep[20010],siz[20010],top[20010],fa[20010],son[20010];
struct edge
{int u,v,w,next;
}e[40010];
struct node
{int sum,maxn,minn;bool lazy;
}tree[100010];
void add(int x,int y,int z)
{e[++tot].u=x;e[tot].v=y;e[tot].w=z;e[tot].next=first[x];first[x]=tot;
}
void dfs1(int now)
{siz[now]=1;for (int i=first[now];i;i=e[i].next)if (fa[now]!=e[i].v){dep[e[i].v]=dep[now]+1;fa[e[i].v]=now;dfs1(e[i].v);siz[now]+=siz[e[i].v];if (siz[e[i].v]>siz[son[now]]) son[now]=e[i].v;}
}
void dfs2(int now,int tp)
{top[now]=tp;pre[++cnt]=now;L[now]=cnt;if (son[now]) dfs2(son[now],tp);for (int i=first[now];i;i=e[i].next)if (e[i].v!=fa[now]&&e[i].v!=son[now])dfs2(e[i].v,e[i].v);
}
void pushdown(int now)
{if (!tree[now].lazy) return;tree[now<<1].lazy^=1;tree[now<<1|1].lazy^=1;swap(tree[now<<1].maxn,tree[now<<1].minn);tree[now<<1].maxn=-tree[now<<1].maxn;tree[now<<1].minn=-tree[now<<1].minn;tree[now<<1].sum=-tree[now<<1].sum;swap(tree[now<<1|1].maxn,tree[now<<1|1].minn);tree[now<<1|1].maxn=-tree[now<<1|1].maxn;tree[now<<1|1].minn=-tree[now<<1|1].minn;tree[now<<1|1].sum=-tree[now<<1|1].sum;tree[now].lazy=0;
}
void pushup(int now)
{tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;tree[now].maxn=max(tree[now<<1].maxn,tree[now<<1|1].maxn);tree[now].minn=min(tree[now<<1].minn,tree[now<<1|1].minn);
}
void build(int now,int begin,int end)
{if (begin==end) {tree[now].sum=tree[now].minn=tree[now].maxn=val[pre[end]];return;}int mid=(begin+end)>>1;build(now<<1,begin,mid);build(now<<1|1,mid+1,end);pushup(now);
}
void update(int now,int begin,int end,int pos,int num)
{if (begin==end) {tree[now].lazy=0;tree[now].sum=tree[now].minn=tree[now].maxn=num;return;}pushdown(now);int mid=(begin+end)>>1;if (mid>=pos) update(now<<1,begin,mid,pos,num);else update(now<<1|1,mid+1,end,pos,num);pushup(now);
}
void oppo(int now,int begin,int end,int l,int r)
{if (l<=begin&&end<=r){tree[now].lazy^=1;tree[now].sum=-tree[now].sum;swap(tree[now].minn,tree[now].maxn);tree[now].minn=-tree[now].minn;tree[now].maxn=-tree[now].maxn;return;}pushdown(now);int mid=(begin+end)>>1;if (mid>=l) oppo(now<<1,begin,mid,l,r);if (mid<r) oppo(now<<1|1,mid+1,end,l,r);pushup(now);
}
int get_max(int now,int begin,int end,int l,int r)
{if (l<=begin&&end<=r) return tree[now].maxn;pushdown(now);int ans=-Inf,mid=(begin+end)>>1;if (mid>=l) ans=max(get_max(now<<1,begin,mid,l,r),ans);if (mid<r) ans=max(get_max(now<<1|1,mid+1,end,l,r),ans);return ans;
}
int get_min(int now,int begin,int end,int l,int r)
{if (l<=begin&&end<=r) return tree[now].minn;pushdown(now);int ans=Inf,mid=(begin+end)>>1;if (mid>=l) ans=min(get_min(now<<1,begin,mid,l,r),ans);if (mid<r) ans=min(get_min(now<<1|1,mid+1,end,l,r),ans);return ans;
}
int get_sum(int now,int begin,int end,int l,int r)
{if (l<=begin&&end<=r) return tree[now].sum;pushdown(now);int ans=0,mid=(begin+end)>>1;if (mid>=l) ans+=get_sum(now<<1,begin,mid,l,r);if (mid<r) ans+=get_sum(now<<1|1,mid+1,end,l,r);return ans;
}
void solve(int l,int r)
{int minn=Inf,maxn=-Inf,ans=0,f1=top[l],f2=top[r];while (f1!=f2){if (dep[f1]<dep[f2]) swap(f1,f2),swap(l,r);if (ch=='N') oppo(1,1,cnt,L[f1],L[l]);else if (ch=='S') ans+=get_sum(1,1,cnt,L[f1],L[l]);else if (ch=='I') minn=min(minn,get_min(1,1,cnt,L[f1],L[l]));else maxn=max(maxn,get_max(1,1,cnt,L[f1],L[l]));l=fa[f1];f1=top[l];}if (dep[l]>dep[r]) swap(l,r);if (l==r){if (ch=='S') {printf("%d\n",ans);return;}if (ch=='I') {printf("%d\n",minn);return;}if (ch=='A') {printf("%d\n",maxn);return;}}l=son[l];if (ch=='N') oppo(1,1,cnt,L[l],L[r]);else if (ch=='S') ans+=get_sum(1,1,cnt,L[l],L[r]),printf("%d\n",ans);else if (ch=='I') minn=min(minn,get_min(1,1,cnt,L[l],L[r])),printf("%d\n",minn);else if (ch=='A')maxn=max(maxn,get_max(1,1,cnt,L[l],L[r])),printf("%d\n",maxn);
}
main()
{scanf("%d",&n);int x,y,z;for (int i=1;i<n;i++)scanf("%d%d%d",&x,&y,&z),x++,y++,add(x,y,z),add(y,x,z);dfs1(1);dfs2(1,1);for (int i=1;i<=tot;i++){if (dep[e[i].u]>dep[e[i].v]) swap(e[i].u,e[i].v);val[e[i].v]=e[i].w;}build(1,1,cnt);scanf("%d",&m);while (m--){ch=getchar();while (ch!='S'&&ch!='C'&&ch!='M'&&ch!='N') ch=getchar();if (ch=='C') {scanf("%d%d",&x,&y);update(1,1,cnt,L[e[x<<1].v],y);continue;}else if (ch=='S') getchar(),getchar();else if (ch=='M') ch=getchar(),getchar();scanf("%d%d",&x,&y);solve(x+1,y+1);}
}

【BZOJ2157】旅游,树链剖分练习相关推荐

  1. P1505 [国家集训队]旅游 树链剖分

    题目链接 题意:树上更新某一点权值,更新两点简单路径权值,查询最大,最小,和 思路:思路应该比较简单,就是树链剖分后用线段树维护区间最大最小以及区间和. 但是本题比较特殊的是给的边权,转化为点权即可. ...

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

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

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

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

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

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

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

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

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

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

  7. 【ZJOI2008】树的统计(树链剖分)

    传送门 Solution: 就是树链剖分入门题啦~ // luogu-judger-enable-o2 #include<bits/stdc++.h> #define N 30005 #d ...

  8. 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)

    题目链接 题意: 给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作: 1 u v:u到v路径(最短)上的边都取成相反的颜色 2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一 ...

  9. 【模板】树链剖分 P3384

    题目链接 //部分转自:https://www.luogu.org/problemnew/solution/P3384 初学树链剖分,感觉这个模板题还是容易理解的,但是实在是码量很大的. 知识点: 重 ...

最新文章

  1. 是时候转型 Serverless 来玩微服务了吗?
  2. 第六章勘误以及Normalization算法不完整
  3. SAP S/4HANA里KPI tile的一个具体例子
  4. VS2015 代码左缩进
  5. 计算机科学导论第五版_五月份将开始提供438项免费在线编程和计算机科学课程
  6. Spring Boot中使用@Async实现异步调用
  7. codeblocks如何让输出结果 空格_简单讲讲如何实现两个正整数相加,然后输出这个结果...
  8. 简历避免采坑总结——为什么你的简历杳无音信?程序员的简历该怎么写?看这一篇就够了!毕业生快进 (待更新)
  9. 日期的前端验证 jquery
  10. 5.11 学习日记,首页banner做好了
  11. php查询mongo数据库效率,2000000万数据库 MongoDB 查询速度慢
  12. 河南农业大学计算机试题,河南农业大学计算机vb考试必出
  13. android开发工具哪个好_小程序开发工具怎么用?哪个好用?
  14. 数据结构之二叉树--转载
  15. C# 简单封装一个XML文件读取类
  16. 精通javascript学习笔记
  17. 本地快速搭建FTP服务器
  18. CSDN格式字体颜色入门
  19. 【软件测试】黑盒测试方法小结
  20. [Ynoi2018]五彩斑斓的世界

热门文章

  1. Vue-Router中History模式【华为云分享】
  2. 无码系列-3-代码架构约束
  3. mysql 数据目录更换_更改Mysql数据目录,这个坑你可能也趟过~
  4. ZooKeeper的安装和API
  5. 使用CLion配置第一个FLTK界面
  6. R语言含中文数据导入的方法
  7. 【文献学习】强化学习3:基于数据的方法
  8. python爬取两个网站_python-2:爬取某个网页(虎扑)帖子的标题做词云图
  9. 微信开发---微信网页授权、JS-SDK和微信公众号的基本设置
  10. ol+天地图+geoserver_GeoServer的WMS服务加载到天地图