P3128 [USACO15DEC]Max Flow P(树上倍增和树链剖分)
思路1(树上倍增$ + $树上差分)
每次都修改一条从\(u\)到\(v\),不就是树上差分的专门操作吗??
直接用倍增求\(LCA\),每次\(d[u]++,d[v]++,d[LCA(u,v)]--,d[f[LCA(u,v)][0]]--\)。
最后记得算下前缀和。
代码1
#include <iostream>
#include <cstring>
using namespace std;
const int N = 50010,M = 2 * N,MAX_LOG = 20;
int n,m;
int h[N],e[M],ne[M],idx;
int w[N];
int dep[N];
int f[N][MAX_LOG];
void add (int a,int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void dfs1 (int u,int fa) {
f[u][0] = fa;
for (int i = 1;i <= MAX_LOG - 1;i++) f[u][i] = f[f[u][i - 1]][i - 1];
for (int i = h[u];~i;i = ne[i]) {
int j = e[i];
if (j == fa) continue;
dep[j] = dep[u] + 1;
dfs1 (j,u);
}
}
int get_LCA (int a,int b) {
if (dep[a] < dep[b]) swap (a,b);
for (int i = MAX_LOG - 1;i >= 0;i--) {
if (dep[f[a][i]] >= dep[b]) a = f[a][i];
}
if (a == b) return a;
for (int i = MAX_LOG - 1;i >= 0;i--) {
if (f[a][i] != f[b][i]) a = f[a][i],b = f[b][i];
}
return f[a][0];
}
int dfs2 (int u,int fa) {
int ans = 0;
for (int i = h[u];~i;i = ne[i]) {
int j = e[i];
if (j == fa) continue;
ans = max (ans,dfs2 (j,u));
w[u] += w[j];
}
return max (ans,w[u]);
}
int main () {
memset (h,-1,sizeof (h));
cin >> n >> m;
for (int i = 1;i <= n - 1;i++) {
int a,b;
cin >> a >> b;
add (a,b),add (b,a);
}
dfs1 (1,0);
while (m--) {
int a,b;
cin >> a >> b;
int anc = get_LCA (a,b);
w[a]++,w[b]++,w[anc]--,w[f[anc][0]]--;
}
cout << dfs2 (1,0) << endl;
return 0;
}
思路2(树链剖分)
修改一条\(u\)到\(v\)的路径,查询整棵树的最大值,不就是树剖的模板吗??
直接套模板(懒得讲
代码2
#include <iostream>
#include <cstring>
using namespace std;
const int N = 50010,M = 2 * N,MAX_LOG = 20;
int n,m;
int h[N],e[M],ne[M],idx;
int timestamp;
int dep[N],s[N],son[N],fa[N];
int id[N],top[N];
struct segment_tree_node {
int l,r;
int maxx,add;
}tr[4 * N];
void add (int a,int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void push_up (int u) {
tr[u].maxx = max (tr[u << 1].maxx,tr[u << 1 | 1].maxx);
}
void push_down (int u) {
auto &root = tr[u],&left = tr[u << 1],&right = tr[u << 1 | 1];
if (root.add) {
left.maxx += root.add,left.add += root.add;
right.maxx += root.add,right.add += root.add;
root.add = 0;
}
}
void build_segment_tree (int u,int l,int r) {
if (l == r) {
tr[u] = {l,r,0,0};
return ;
}
tr[u] = {l,r};
int mid = l + r >> 1;
build_segment_tree (u << 1,l,mid),build_segment_tree (u << 1 | 1,mid + 1,r);
push_up (u);
}
void modify (int u,int l,int r,int d) {
if (l <= tr[u].l && tr[u].r <= r) {
tr[u].add += d,tr[u].maxx += d;
return ;
}
push_down (u);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid) modify (u << 1,l,r,d);
if (r >= mid + 1) modify (u << 1 | 1,l,r,d);
push_up (u);
}
int query_max (int u,int l,int r) {
if (l <= tr[u].l && tr[u].r <= r) return tr[u].maxx;
push_down (u);
int mid = l + r >> 1;
int ans = 0;
if (l <= mid) ans = max (ans,query_max (u << 1,l,r));
if (r >= mid + 1) ans = max (ans,query_max (u << 1 | 1,l,r));
return ans;
}
void dfs1 (int u,int f) {
dep[u] = dep[f] + 1,s[u] = 1,fa[u] = f;
for (int i = h[u];~i;i = ne[i]) {
int j = e[i];
if (j == f) continue;
dfs1 (j,u);
s[u] += s[j];
if (s[j] > s[son[u]]) son[u] = j;
}
}
void dfs2 (int u,int top_node) {
id[u] = ++timestamp,top[u] = top_node;
if (!son[u]) return ;
dfs2 (son[u],top_node);
for (int i = h[u];~i;i = ne[i]) {
int j = e[i];
if (j == fa[u] || j == son[u]) continue;
dfs2 (j,j);
}
}
void modify_path (int a,int b) {
while (top[a] != top[b]) {
if (dep[top[a]] < dep[top[b]]) swap (a,b);
modify (1,id[top[a]],id[a],1);
a = fa[top[a]];
}
if (dep[a] > dep[b]) swap (a,b);
modify (1,id[a],id[b],1);
}
int query_subtree (int u) {
return query_max (1,id[u],id[u] + s[u] - 1);
}
int main () {
memset (h,-1,sizeof (h));
cin >> n >> m;
for (int i = 1;i <= n - 1;i++) {
int a,b;
cin >> a >> b;
add (a,b),add (b,a);
}
build_segment_tree (1,1,n),dfs1 (1,0),dfs2 (1,1);
while (m--) {
int a,b;
cin >> a >> b;
modify_path (a,b);
}
cout << query_subtree (1) << endl;
return 0;
}
P3128 [USACO15DEC]Max Flow P(树上倍增和树链剖分)的更多相关文章
- [luogu P3128][USACO15DEC]Max Flow [LCA][树上差分]
题目描述 Farmer John has installed a new system of pipes to transport milk between the stalls in his b ...
- 【HAOI2015】树上操作(树链剖分)
题面 Description 有一棵点数为N的树,以点1为根,且树点有边权.然后有M个操作,分为三种: 操作1:把某个节点x的点权增加a. 操作2:把某个节点x为根的子树中所有点的点权都增加a. 操作 ...
- 洛谷P3178 树上操作 [HAOI2015] 树链剖分
正解:树链剖分+线段树 解题报告: 传送门! 树链剖分+线段树算是基操了趴,,, 就无脑码码码,没有任何含金量,不需要动脑子,然后码量其实也不大,就很爽 比树剖的板子还要板子一些hhhhh 放下代码就 ...
- [HAOI2015]树上操作(树链剖分)
[HAOI2015]树上操作(luogu) Description 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增 ...
- BZOJ_4034 [HAOI2015]树上操作 【树链剖分dfs序+线段树】
一 题目 [HAOI2015]树上操作 二 分析 树链剖分的题,这里主要用到了$dfs$序,这题比较简单的就是不用求$lca$. 1.和树链剖分一样,先用邻接链表建双向图. 2.跑两遍$dfs$,其实 ...
- 模板 树上求LCA 倍增和树链剖分
//233 模板 LCA void dfs(int x,int f){ for(int i=0;i<E[x].size();i++){ int v = E[x][i]; if(v==f)cont ...
- 「HAOI2015」「LuoguP3178」树上操作(树链剖分
题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...
- 洛谷P4689 [Ynoi2016]这是我自己的发明(树上莫队+树链剖分)
题目描述 您正在打galgame,然后突然家长进来了,于是您假装在写数据结构题: 给一个树,n 个点,有点权,初始根是 1. m 个操作,每次操作: 1.将树根换为 x. 2.给出两个点 x,y,从 ...
- 4034. [HAOI2015]树上操作【树链剖分】
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...
- [HAOI2015]树上操作(树链剖分,线段树)
题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 ...
随机推荐
- Adversarial seeded sequence growing for weakly-supervised temporal action localization概述
0.前言 相关资料: 论文 github 论文解读 论文基本信息: 领域:弱监督时序动作定位综述 更新时间:ACM MM2019(2019.8.7) 1.针对的问题 大多数现有的框架依赖于类激活序列( ...
- Elasticsearch集群部署和运维命令
Elasticsearch集群部署 下载tar包 在"https://www.elastic.co/cn/downloads/elasticsearch"页面,有 past rel ...
- Blender2.8 使用笔记
基本 视口 小键盘/: 隔离 Z:切换线框与实体显示 Ctrl+Alt+Q : 多视图切换 Shift+C:回原点 Shift+鼠标中键 视口平移 Ctrl+上下移动 视口放大缩小 导出FBX 几何数 ...
- 语言-页面-模板-thymeleaf
一.语法 二.使用 Thymeleaf入门到吃灰 - 鞋破露脚尖儿 - 博客园 (cnblogs.com)
- Token过期处理
Token用于进行接口鉴权,但是Token具有由后端设置的过期时间,当Token过期以后,就无法再请求数据了 项目中后端设置的过期时间为24h,测试时我们可以手动修改token值让Token失效 处理 ...
- Linux 压测及监控工具Nmon
一.带宽 1. 查看网卡的网络 ethtool:查看宽带大小,语法:ethtool 网卡名称,如:ethtool ens192: 2. 实时统计网卡宽带使用率nload A. 安装nload wget ...
- MySQL系列-详解mysql数据类型
MySQL数据类型 (1)数值类型 1.整数型 2.浮点型 3.定点型 (2)日期时间类型 (3)字符串类型 MySQL字段属性 1.空\不为空值:NULL.NOT NULL 2.主键:primary ...
- css 背景渐变
1.渐变从左到右 background: linear-gradient(to right,#000,#fff); 2.渐变从上到下 background: linear-gradient(tobot ...
- 建议收藏| 学python的看过来,Python 史上最全第三方库收集
发现一个宝藏网站: GitHub 上有一个 Awesome - XXX 系列的资源整理,这个系列以"全"闻名,但凡是有一定知识度的领域.语言.框架等,都有自己的 awesome-x ...
- cin和缓存区问题
稍微记录一下今天刷题遇到的C++问题 看到使用while(cin >> s);来读取最后一个字符串.百度了一下发现cin以空格,制表符和回车为终止依据.也就是说我输入"abc 1 ...