思路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. JS中有关(...)的介绍

    1,深拷贝一个对象 如上图所示,obj和tmp是完全两个独立的对象,互不影响. 2,数组复制 如上图所示,arr和tmp是两个完全独立的数组,彼此之间的值互不影响. 3,函数形参中的使用 这里的... ...

  2. 89. 格雷编码 (Medium)

    问题描述 89. 格雷编码 (Medium) n 位格雷码序列 是一个由 2ⁿ 个整数组成的序列,其中: 每个整数都在范围 [0, 2ⁿ - 1] 内(含 0 和 2ⁿ - 1) 第一个整数是 0 一 ...

  3. golang中自带base64编码和解码

    package main import ( "encoding/base64" "fmt" "log" ) func main() { in ...

  4. ansible-file

    path参数 :必须参数,用于指定要操作的文件或目录,在之前版本的ansible中,使用dest参数或者name参数指定要操作的文件或目录,为了兼容之前的版本,使用dest或name也可以. stat ...

  5. Jmeter的简单配置和使用

    对于测试大佬来说,最常见的压测工具莫过于Apache旗下的 JMeter . 那么测试大佬经常使用,对于我们后端开发者来说,也是属于必备的一个技能. 接下来咱们就一起简单的配置一下烫手的jmeter ...

  6. omcat启动Publishing failed with multiple errors

    新安装一个tomcat插件.启动的时候就弹错误框.但tomcat还能使用. Publishingfailedwithmultipleerrors Resource is out of sync wit ...

  7. continue的使用

    continue是终止本次循环,进行下一个循环如果要跳到最开始的循环abc : for(){ for(){ for(){ continue abc; } }}

  8. SpringBoot加载相关注解

    springBoot加载 @Configuration 表明该类是一个配置类常常配合@Bean使用,让容器管理对象 @Configuration(proxyBeanMethods = true) pr ...

  9. Excel入门

    Excel入门 一.Excel 2019工作界面介绍 文件菜单 选项卡.功能区和组 快速访问工具栏 公式编辑栏(名称框.编辑按钮.编辑栏) 内容编辑区(单元格.行号.列标.水平滚动条.垂直滚动条.工作 ...

  10. layui相关问题总结

    1.layui table回显选中 1) radio: done:function(res, curr, count){ for(var i = 0; i < res.data.length; ...