思路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(树上倍增和树链剖分)的更多相关文章

  1. [luogu P3128][USACO15DEC]Max Flow [LCA][树上差分]

    题目描述 Farmer John has installed a new system of  pipes to transport milk between the  stalls in his b ...

  2. 【HAOI2015】树上操作(树链剖分)

    题面 Description 有一棵点数为N的树,以点1为根,且树点有边权.然后有M个操作,分为三种: 操作1:把某个节点x的点权增加a. 操作2:把某个节点x为根的子树中所有点的点权都增加a. 操作 ...

  3. 洛谷P3178 树上操作 [HAOI2015] 树链剖分

    正解:树链剖分+线段树 解题报告: 传送门! 树链剖分+线段树算是基操了趴,,, 就无脑码码码,没有任何含金量,不需要动脑子,然后码量其实也不大,就很爽 比树剖的板子还要板子一些hhhhh 放下代码就 ...

  4. [HAOI2015]树上操作(树链剖分)

    [HAOI2015]树上操作(luogu) Description 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增 ...

  5. BZOJ_4034 [HAOI2015]树上操作 【树链剖分dfs序+线段树】

    一 题目 [HAOI2015]树上操作 二 分析 树链剖分的题,这里主要用到了$dfs$序,这题比较简单的就是不用求$lca$. 1.和树链剖分一样,先用邻接链表建双向图. 2.跑两遍$dfs$,其实 ...

  6. 模板 树上求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 ...

  7. 「HAOI2015」「LuoguP3178」树上操作(树链剖分

    题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...

  8. 洛谷P4689 [Ynoi2016]这是我自己的发明(树上莫队+树链剖分)

    题目描述 您正在打galgame,然后突然家长进来了,于是您假装在写数据结构题: 给一个树,n 个点,有点权,初始根是 1. m 个操作,每次操作: 1.将树根换为 x. 2.给出两个点 x,y,从  ...

  9. 4034. [HAOI2015]树上操作【树链剖分】

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...

  10. [HAOI2015]树上操作(树链剖分,线段树)

    题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 ...

随机推荐

  1. 面试视频知识点整理1-7(http协议)

    http协议类 1)http协议的主要特点             简单快速   统一资源符 灵活          通过http协议,可以修改http头,完成不同数据类型的传输 无连接        ...

  2. MongoDB 用户及权限增删

    本文主要是MongoDB4.X的操作 一.MongoDB用户创建   MongoDB采用基于角色的访问控制(RBAC)来确定用户的访问. 授予用户一个或多个角色,确定用户对MongoDB资源的访问权限 ...

  3. 上传镜像到harbor

    https://blog.csdn.net/weixin_45335305/article/details/123817541

  4. 【Java】时间类型

    Date 转 timeStamp long time = System.currentTimeMillis(); // 秒级 long time = System.currentTimeMillis( ...

  5. [OC] 统计代码行数

    1.打开终端 2. cd 路径,或者 输入cd ,然后把要统计代码的工程拖入终端,就会出现工程的路径. 然后按下回车. 3.输入: find . -name "*.m" -or - ...

  6. word常用快捷键

    输入公式:Alt + = 小写转大写:Shift + F3 \double{R}是实数符号

  7. 随机生成四则运算表达式【Unity】

    根据自己项目需求调整代码中表达式的公共方法 using System.Collections; using System.Collections.Generic; using System; usin ...

  8. Java实验 继承与接口

     一.实验目的 1.理解 Java 语言的继承和多态特性: 2.掌握变量的隐藏.方法的覆盖.重载: 3.掌握抽象类和接口的使用. 二.实验要求 1.根据实验步骤中提出的要求,使用eclipse等开发工 ...

  9. python中列表,字典,字符串常用操作

    1. 列表操作 分类 关键字 / 函数 / 方法 说明 增加 列表.append(值) 在末尾追加值   列表.insert(索引, 值) 在指定位置插入值, 超过索引会追加值   列表.extend ...

  10. 如何卸载inventor 2023?怎么把inventor彻底卸载删除干净重新安装的方法【转载】

    inventor 2023卸载重新安装方法,使用清理卸载工具箱完全彻底删除干净inventor 2023各种残留注册表和文件.inventor 2023显示已安装或者报错出现提示安装未完成某些产品无法 ...