Codeforces 903G Yet Another Maxflow Problem - 线段树
题目传送门
题目大意
给定一个网络。网络分为$A$,$B$两个部分,每边各有$n$个点。对于$A_{i} \ (1\leqslant i < n)$会向$A_{i + 1}$连一条容量为$x_{i}$的有向边,对于$B_{i} \ (1\leqslant i < n)$会向$B_{i + 1}$连一条容量为$y_{i}$的有向边。$A$和$B$之间有$m$条边,起点为$A_{u_{i}}$,终点为$B_{v_{i}}$,容量为$w_{i}$的有向边。要求支持多次修改边的容量,询问$A_{1}$到$B_{n}$的最大流。
看起来不会退流的样子,所以应该可以用数据结构乱搞搞就能做出来。于是我想了很久但仍然不会。
因为最大流的流量等于最小割的容量,所以最大流不好做的时候考虑最小割。
直接考虑最小割的求解变成了最大流,这样没有用。考虑放宽一下约束条件,找一下怎样的割集是较优的。
一些显而易见的结论:
- 假如在$A$中,割掉$A_{x}$和$A_{x + 1}$之间的有向边,那么割掉$A_{y} \ (y > x)$与$A_{y + 1}$之间的有向边是没有意义的。
- 假如在$B$中,割掉$B_{x}$和$B_{x + 1}$之间的有向边,那么割掉$B_{y} \ (y < x)$与$B_{y + 1}$之间的有向边是没有意义的。
因此,在$A, B$中至多有一条边属于割集。
假设在$A$中被割掉的边是$(A_{x}, A_{x + 1})$,在$B$中被割掉的边是$B_{y}, B_{y + 1}$,那么任意$(A_{u}, B_{v}) \ (u \leqslant x \wedge v > y)$都是属于这个割集的。
因此,割的大小可以看做三部分:在$A$中的割集大小,在$B$中的割集大小,在$A, B$间的割集大小。
由于后两部分不会改变,考虑计算出它们。
考虑在$A$中从小到大枚举$A_{x}$,表示割掉$A_{x}$和$A_{x + 1}$之间的边,如果$x = n$表示不存在这条边。
那么下面要做的事情是在$B$中找到一个最优决策点$y$,使得后两部分的和最小。
对于每加入一条在$A,B$间的边,对答案造成的影响是连续的一段。
所以我们只需要写一个支持区间加,求$[1, n]$的最小值的线段树就好了。
到此,我们完美解决这道题了吗?
不,还剩下合并两部分的答案。这个可以用一个可删堆来维护。
时间复杂度$O((n + m + q)\log n)$。
Code
/**
* Codeforces
* Problem#903G
* Accepted
* Time: 451ms
* Memory: 31200k
*/
#include <bits/stdc++.h>
#ifdef WIN32
#define Auto "%I64d"
#else
#define Auto "%lld"
#endif
using namespace std; #define ll long long typedef class SegTreeNode {
public:
ll minv, lazy;
SegTreeNode *l, *r; SegTreeNode():minv(), lazy(), l(NULL), r(NULL) { } void pushUp() {
minv = min(l->minv, r->minv);
} void pushDown() {
l->minv += lazy, r->minv += lazy;
l->lazy += lazy, r->lazy += lazy;
lazy = ;
}
}SegTreeNode; #define Limit 500000 SegTreeNode pool[Limit];
SegTreeNode* top = pool; SegTreeNode* newnode() {
return top++;
} typedef class SegTree {
public:
SegTreeNode* rt; SegTree() { }
SegTree(int n, int* ar) {
build(rt, , n, ar);
} void build(SegTreeNode*& p, int l, int r, int *ar) {
p = newnode();
if (l == r) {
p->minv = ar[l];
return;
}
int mid = (l + r) >> ;
build(p->l, l, mid, ar);
build(p->r, mid + , r, ar);
p->pushUp();
} void update(SegTreeNode*& p, int l, int r, int ql, int qr, int val) {
if (l == ql && r == qr) {
p->minv += val, p->lazy += val;
return;
}
if (p->lazy) p->pushDown();
int mid = (l + r) >> ;
if (qr <= mid)
update(p->l, l, mid, ql, qr, val);
else if (ql > mid)
update(p->r, mid + , r, ql, qr, val);
else {
update(p->l, l, mid, ql, mid, val);
update(p->r, mid + , r, mid + , qr, val);
}
p->pushUp();
}
}SegTree; #define pii pair<int, int> typedef class Heap {
public:
priority_queue<ll> que;
priority_queue<ll> del; Heap() { } void insert(ll x) {
que.push(-x);
} void remove(ll x) {
del.push(-x);
} ll top() {
while (!que.empty() && !del.empty() && que.top() == del.top())
que.pop(), del.pop();
return -que.top();
}
}Heap; int n, m, q;
int *cs1, *cs2;
vector<pii> *g;
Heap hp;
SegTree st; inline void init() {
scanf("%d%d%d", &n, &m, &q);
cs1 = new int[(n + )];
cs2 = new int[(n + )];
g = new vector<pii>[(n + )];
cs1[n] = , cs2[] = ;
for (int i = ; i < n; i++)
scanf("%d%d", cs1 + i, cs2 + i + );
for (int i = , u, v, w; i <= m; i++) {
scanf("%d%d%d", &u, &v, &w);
g[u].push_back(pii(v, w));
}
} ll *olds;
inline void solve() {
olds = new ll[(n + )];
st = SegTree(n, cs2);
for (int i = ; i <= n; i++) {
for (int j = ; j < (signed) g[i].size(); j++)
st.update(st.rt, , n, , g[i][j].first, g[i][j].second);
hp.insert(olds[i] = cs1[i] + st.rt->minv);
// cerr << olds[i] << endl;
}
printf(Auto"\n", hp.top());
int p, nw;
while (q--) {
scanf("%d%d", &p, &nw);
hp.remove(olds[p]);
olds[p] = olds[p] - cs1[p] + nw, cs1[p] = nw;
hp.insert(olds[p]);
printf(Auto"\n", hp.top());
}
} int main() {
init();
solve();
return ;
}
Codeforces 903G Yet Another Maxflow Problem - 线段树的更多相关文章
- 【CF903G】Yet Another Maxflow Problem 线段树
[CF903G]Yet Another Maxflow Problem 题意:一张图分为两部分,左边有n个点A,右边有m个点B,所有Ai->Ai+1有边,所有Bi->Bi+1有边,某些Ai ...
- codeforces 1217E E. Sum Queries? (线段树
codeforces 1217E E. Sum Queries? (线段树 传送门:https://codeforces.com/contest/1217/problem/E 题意: n个数,m次询问 ...
- [Codeforces 266E]More Queries to Array...(线段树+二项式定理)
[Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...
- [Codeforces 280D]k-Maximum Subsequence Sum(线段树)
[Codeforces 280D]k-Maximum Subsequence Sum(线段树) 题面 给出一个序列,序列里面的数有正有负,有两种操作 1.单点修改 2.区间查询,在区间中选出至多k个不 ...
- Codeforces 1089K - King Kog's Reception - [线段树][2018-2019 ICPC, NEERC, Northern Eurasia Finals Problem K]
题目链接:https://codeforces.com/contest/1089/problem/K time limit per test: 2 seconds memory limit per t ...
- Codeforces 803G Periodic RMQ Problem 线段树
Periodic RMQ Problem 动态开点线段树直接搞, 我把它分成两部分, 一部分是原来树上的, 一部分是后来染上去的,两个部分取最小值. 感觉有点难写.. #include<bits ...
- Codeforces 444 C. DZY Loves Colors (线段树+剪枝)
题目链接:http://codeforces.com/contest/444/problem/C 给定一个长度为n的序列,初始时ai=i,vali=0(1≤i≤n).有两种操作: 将区间[L,R]的值 ...
- Codeforces Gym 100513F F. Ilya Muromets 线段树
F. Ilya Muromets Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100513/probl ...
- Codeforces 834D The Bakery【dp+线段树维护+lazy】
D. The Bakery time limit per test:2.5 seconds memory limit per test:256 megabytes input:standard inp ...
随机推荐
- webpack 解决跨域问题
一.webpack 内置了 http-proxy-middleware 可以解决 请求的 URL 代理的问题 安装:npm install --save http-proxy-middleware 二 ...
- java生成随机六位数的验证码&随机生成十位数ValidCode码,用于邮件的验证&检查是不是符合为合法的中国的手机号码
package com.demo.test1; import java.security.NoSuchAlgorithmException; import java.security.SecureRa ...
- Rest概念学习
参考文章 http://www.cnblogs.com/shanyou/archive/2012/05/12/2496959.html http://www.cnblogs.com/loveis715 ...
- PM2管理工具的使用
linux上PM2可以管理服务程序,防止程序无故关闭,具有程序守护功能,自动重启服务器程序,监控程序等好处,很方便,具体自己去体会! 官网地址: http://pm2.keymetrics.io/ ...
- 2.匿名类,匿名类对象,private/protected/public关键字、abstract抽象类,抽象方法、final关键字的使用,多线程Thread类start方法原理
package com.bawei.multithread; //注意:模板方法我们通常使用抽象类或者抽象方法!这里我们为了方便在本类中使用就没有使用抽象类/抽象方法 public class Tem ...
- Shader1.0学习笔记之SetTexture
1.语法 SetTexture [TextureName] {Texture Block} 2.Texture block combine 命令 combine src1 * src2 越乘越暗 c ...
- Sitecore CMS中如何命名项目名称
如何在Sitecore CMS中命名项目,以及配置命名限制,“显示名称”是什么以及如何使用它. 任何其他名称的项目 当创建Sitecore的项目,内容编辑器要求制作者为新建项目提供名称.输入的名称将其 ...
- Linux 运维测试及第三应用及测试工具
一 .第三方应用及测试工具链接地址 https://pan.baidu.com/s/1rLQ5NCZvxcy93YQ4fGFaBQ 1.linux LSI系列raid卡监测工具 1)使用参数详解链接: ...
- codeforces 980A Links and Pearls
题意: 有珍珠和线,问能否重新安排使得相邻珍珠之间的线的数量相等. 思路: 首先,珍珠为0或者线为0,那么都满足条件: 其次,如果珍珠的个数大于线的个数,那么肯定不满足条件: 然后,如果线的个数能够被 ...
- Python大神成长之路: 第三次学习记录 集合 函数 装饰 re
学习记录day03 字符串可以直接切片,But字符串不可修改 字符串修改:生成了一个新的字符串 LIst修改,在原基础上修改(原内存上) 集合是一个无序的,不重复的数据组合,它的主要作用如 ...