整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


题目链接

https://hydro.ac/d/bzoj/p/2157

是 hydro 的 BZOJ 修复工程 !

Problem

给定一棵 nnn 个节点的树,边带权,编号 0∼n−10 \sim n-10∼n−1,需要支持五种操作:

C i w :将输入的第 iii 条边权值改为 www
N u v :将 u,vu,vu,v 节点之间的边权都变为相反数
SUM u v :询问 u,vu,vu,v 节点之间边权和
MAX u v :询问 u,vu,vu,v 节点之间边权最大值
MIN u v :询问 u,vu,vu,v 节点之间边权最小值

保证任意时刻所有边的权值都在 [−1000,1000][-1000,1000][−1000,1000] 内。

对于 100%100\%100% 的数据,1≤n,m≤2×1051\le n,m \le 2\times 10^51≤n,m≤2×105。

Solution

树上问题往往都是点带权,可以直接树链剖分解决。但是本题是边带权,考虑一个点最多只有一个父亲结点,我们可以将这个点与其父亲结点之间边的边权转化为这个点的点权即可。注意我们在进行树链剖分查询和修改路径的时候,端点 xxx 的父亲结点 fa[x]fa[x]fa[x] 是不在路径上的,因为父亲结点 fa[x]fa[x]fa[x] 的点权代表的是点 fa[x]fa[x]fa[x] 与它的父亲结点 fa[fa[x]]fa[fa[x]]fa[fa[x]] 之间的边权,因此,在查询和修改的时候,最后左端点为 id[x]+1id[x]+1id[x]+1,在实现的时候也要注意此类的细节。

转化为点权之后,树链剖分即可。

我们使用线段树维护题目中的五种操作,对于操作2,我们维护一个 tag 即可,每次修改的时候直接异或取反。

然后思维上就没有什么难度了,但是长是真的长,随随便便半个小时三百行代码呼你脸上…

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 6, maxm = maxn << 1 | 7, INF = 0x3f3f3f3f;template <typename T> inline void read(T &x)
{x = 0;int f = 0;char ch = getchar();while(!isdigit(ch)) {f = ch == '-', ch = getchar();}while(isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}if(f) x = -x;
}template <typename T> void print(T x)
{if(x < 0) putchar ('-'), x = -x;if(x > 9) print (x / 10);putchar (x % 10 + '0');
}int n, m, s, t, k;
ll ans;
int head[maxn], ver[maxm], edge[maxm], nex[maxm], tot;
bool vis[maxn];
int val[maxn];
int a_after[maxn];struct Edge
{int x, y;
}side[maxn];void add(int x, int y, int z)
{ver[tot] = y;edge[tot] = z;nex[tot] = head[x];head[x] = tot ++ ;
}void init()
{memset(head, -1, sizeof head);tot = 0;
}struct Segment_Tree
{struct node {int l, r;int sum;
//      int laz; int tag;//相反数的tagint maxx;int minn;}tr[maxn << 2];void pushup(int p){node &l = tr[p << 1], &r = tr[p << 1 | 1], &rt = tr[p];rt.sum = l.sum + r.sum;rt.maxx = max(l.maxx, r.maxx);rt.minn = min(l.minn, r.minn);}void pushdown(int p){node &l = tr[p << 1], &r = tr[p << 1 | 1], &rt = tr[p];if(rt.tag == 0) return ;l.tag ^= 1, r.tag ^= 1;l.sum = -l.sum, r.sum = -r.sum;l.maxx = -l.maxx, r.maxx = -r.maxx;l.minn = -l.minn, r.minn = -r.minn;swap(l.maxx, l.minn), swap(r.maxx, r.minn);rt.tag = 0;}void build(int p, int l, int r){tr[p].l = l, tr[p].r = r;if(l == r) {tr[p].sum = tr[p].minn = tr[p].maxx = a_after[l];return ;}   int mid = l + r >> 1;build(p << 1, l, mid);build(p << 1 | 1, mid + 1, r);pushup(p);}void modify(int p, int x, int k){if(tr[p].l == tr[p].r) {tr[p].sum = tr[p].minn = tr[p].maxx = k;return ;}if(tr[p].tag) pushdown(p);int mid = tr[p].l + tr[p].r >> 1;if(x <= mid) modify(p << 1, x, k);if(x > mid) modify(p << 1 | 1, x, k);pushup(p);}void _reverse(int p, int l, int r){if(tr[p].l >= l && tr[p].r <= r) {tr[p].tag ^= 1;tr[p].sum = -tr[p].sum;tr[p].minn = -tr[p].minn;tr[p].maxx = -tr[p].maxx;swap(tr[p].minn, tr[p].maxx);return ;}if(tr[p].tag) pushdown(p);int mid = tr[p].l + tr[p].r >> 1;if(l <= mid) _reverse(p << 1, l, r);if(r > mid) _reverse(p << 1 | 1, l, r);pushup(p);}int query_sum(int p, int l, int r){int res = 0;if(tr[p].l >= l && tr[p].r <= r) return tr[p].sum;if(tr[p].tag) pushdown(p);int mid = tr[p].l + tr[p].r >> 1;if(l <= mid) res += query_sum(p << 1, l, r);if(r > mid) res += query_sum(p << 1 | 1, l, r);pushup(p);return res;}int query_max(int p, int l, int r){int res = -INF;if(tr[p].l >= l && tr[p].r <= r) return tr[p].maxx;if(tr[p].tag) pushdown(p);int mid = tr[p].l + tr[p].r >> 1;if(l <= mid) res = max(res, query_max(p << 1, l, r));if(r > mid) res = max(res, query_max(p << 1 | 1, l, r));pushup(p);return res;}int query_min(int p, int l, int r){int res = INF;if(tr[p].l >= l && tr[p].r <= r) return tr[p].minn;if(tr[p].tag) pushdown(p);int mid = tr[p].l + tr[p].r >> 1;if(l <= mid) res = min(res, query_min(p << 1, l, r));if(r > mid) res = min(res, query_min(p << 1 | 1, l, r));pushup(p);return res;}}ST;struct Tree
{ int dfn[maxn], tim;int id[maxn];int siz[maxn], max_size;int hson[maxn];int w[maxn];int depth[maxn], fa[maxn], top[maxn];void dfs1(int x, int father, int deep){depth[x] = deep + 1;fa[x] = father;siz[x] = 1;int max_sizes = -1;for (int i = head[x]; ~i; i = nex[i]) {int y = ver[i];ll z = edge[i];if(y == father) continue;dfs1(y, x, deep + 1);val[y] = z;siz[x] += siz[y];if(siz[y] > max_sizes) max_sizes = siz[y], hson[x] = y;}   } void dfs2(int x, int topfa){dfn[x] = ++ tim;a_after[tim] = val[x];top[x] = topfa;if(hson[x] == 0) return ; dfs2(hson[x], topfa); for (int i = head[x]; ~i; i = nex[i]) {int y = ver[i]; if(y == fa[x] || y == hson[x]) continue;dfs2(y, y);} }void modify_change(int x, int y){int pos;if(depth[side[x].x] > depth[side[x].y])pos = side[x].x;else pos = side[x].y;ST.modify(1, dfn[pos], y);}void modify_reverse(int x, int y){while(top[x] != top[y]) {if(depth[top[x]] < depth[top[y]])swap(x, y);ST._reverse(1, dfn[top[x]], dfn[x]);x = fa[top[x]];}if(depth[x] > depth[y]) swap(x, y);if(x != y) ST._reverse(1, dfn[x] + 1, dfn[y]);//由于边权转点权,下端点要 + 1}int query_sum(int x, int y){int res = 0; while(top[x] != top[y]) {if(depth[top[x]] < depth[top[y]])swap(x, y); res += ST.query_sum(1, dfn[top[x]], dfn[x]);x = fa[top[x]];}if(depth[x] > depth[y]) swap(x, y); if(x != y) ;res += ST.query_sum(1, dfn[x] + 1, dfn[y]); return res;   }int query_max(int x, int y){int res = -INF;while(top[x] != top[y]) {if(depth[top[x]] < depth[top[y]])swap(x, y);res = max(res, ST.query_max(1, dfn[top[x]], dfn[x]));x = fa[top[x]];}if(depth[x] > depth[y]) swap(x, y);if(x != y) res = max(res, ST.query_max(1, dfn[x] + 1, dfn[y])); return res;    }int query_min(int x, int y){int res = INF;while(top[x] != top[y]) {if(depth[top[x]] < depth[top[y]])swap(x, y);res = min(res, ST.query_min(1, dfn[top[x]], dfn[x]));x = fa[top[x]];}if(depth[x] > depth[y]) swap(x, y);if(x != y) res = min(res, ST.query_min(1, dfn[x] + 1, dfn[y])); return res;    }
}T;  int main()
{init();cin >> n;for (int i = 1; i <= n - 1; ++ i) {int x, y, z;read(x), read(y), read(z);x ++ , y ++ ;add(x, y, z);add(y, x, z);side[i].x = x, side[i].y = y;} T.dfs1(1, 0, 0);T.dfs2(1, 1);ST.build(1, 1, n);cin >> m;while(m -- ) {char op[100];int x, y;scanf("%s", op);read(x), read(y);if(op[0] == 'C') {T.modify_change(x, y);}else if(op[0] == 'N') {x ++ , y ++ ;T.modify_reverse(x, y);}else if(op[0] == 'S') {x ++ , y ++ ;print(T.query_sum(x, y));puts("");}else if(op[0] == 'M' && op[1] == 'A') {x ++ , y ++ ;print(T.query_max(x, y));puts("");}else if(op[0] == 'M' && op[1] == 'I') {x ++ , y ++ ;print(T.query_min(x, y));puts("");         }}return 0;
}

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

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

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

  2. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  3. CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...

  4. CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...

  5. P2486 [SDOI2011]染色(树链剖分+线段树)

    题干描述 输入描述 输出格式 对于每个询问操作,输出一行答案. 输入输出样例 输入 #1 复制 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q ...

  6. BZOJ4127Abs——树链剖分+线段树

    题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...

  7. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  8. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  9. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

最新文章

  1. WebStorm常用设置(转载)
  2. Greenplum【问题记录 01】资源组配置后GPCC用户无法认证登录
  3. c#中控制不能从一个case标签贯穿到另一个case标签
  4. 编程基础 垃圾回收_编程中的垃圾回收指南
  5. python如何提高工作效率_用Python的这3个优点,让工作效率提升一倍
  6. java保存图书每日的交易记录
  7. 安卓应用安全指南 4.1.1 创建/使用活动 示例代码
  8. mysql ibtmp1 太大_mysql5.7 ibtmp1文件过大
  9. docker中不能读取带.环境变量的问题
  10. 关于CocoaPods update/CocoaPods install 慢、没反应、卡住的解决方案(Pods升级步骤)
  11. 《Spring实战》读书笔记-第1章 Spring之旅
  12. java定时任务 时间_java 定时任务的执行时间表示-
  13. 可行性分析报告 模板
  14. vbs如何调用c语言函数,vbscript基础教程-自定义函数和过程
  15. matlab centralize,智课雅思词汇---二十三、动词性后缀-ate-fy-ish-ize
  16. 核心单词Word List 46
  17. PIC16 F887 单片机 直流电机PWM调速 PID调速 PID算法
  18. 【培训实验记录】锐捷SDN交换机和控制器部署
  19. new BigDecimal比较大小
  20. mysql多对一[自用]

热门文章

  1. 一文读懂CV中的注意力机制
  2. 【OpenCV 4开发详解】颜色模型与转换
  3. 解决Ubuntu 14.04 Unity桌面环境登录后冻结问题
  4. 【Linux】 字符串和文本处理工具 grep sed awk
  5. tar -cvPf new.tar `rpm -ql vsftpd` 建议不要用绝对路径'/'
  6. iPhone浏览器性能测试
  7. ThreadPoolExecutor使用介绍
  8. 如何开展软件架构之需求分析3
  9. java hello world
  10. 入门月薪8k,3年经验年薪30w,大数据薪酬待遇竟这么高?