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 ...
随机推荐
- ida6.8 android so调试
献给还不会的同学. 我的设备 1.魅族手机,自带root功能 2.ida6.8 1.上传ida 目录下dbgsrv/android_server 到 手机上,这个目录自己可以修改,网上都用的adb p ...
- 34.js----JS 开发者必须知道的十个 ES6 新特性
JS 开发者必须知道的十个 ES6 新特性 这是为忙碌的开发者准备的ES6中最棒的十个特性(无特定顺序): 默认参数 模版表达式 多行字符串 拆包表达式 改进的对象表达式 箭头函数 =&> ...
- sqlserver备份还原数据库时报占用错误
.做项目时遇到这种情形:原来的test_dev数据库,想复制出test_ft供测试用.此时备份test_dev出test_backup文件,想直接还原成test_ft时会报占用错误. 还原数据库:Th ...
- hdu 5126 cdq+Treap+BIT
这题说的是给了三维空间然后操作 寻求在 x1,y1,z1 x2, y2, z2; (x1<x2, y1<y2,z1<z2) 计算出在 以这两个端点为右下和左上端点的方体内的点的 ...
- 大数据处理框架之Strom: Storm----helloword
大数据处理框架之Strom: Storm----helloword Storm按照设计好的拓扑流程运转,所以写代码之前要先设计好拓扑图.这里写一个简单的拓扑: 第一步:创建一个拓扑类含有main方法的 ...
- QWidget 的 close 与 Qt::WA_DeleteOnClose
[1]close 与 Qt::WA_DeleteOnClose简介 1.1 Qt源码 /*! Closes this widget. Returns \c true if the widget was ...
- dict['source'] = list[1],出现这种情况大多是数据的格式发生错误
修改数据的格式
- Gibbs Sampling深入理解
二维Gibbs Sampling算法 Gibbs Sampling是高维概率分布的MCMC采样方法.二维场景下,状态(x, y)转移到(x’, y’),可以分为三种场景 (1)平行于y轴转移,如上图中 ...
- Spring源码阅读(八)
摘要: 本文首先将举例说明如何使用BeanWrapper,然后根据例子中的结果分析BeanWrapper的源码.由于在spring中BeanWrapperImpl是BeanWrapper接口的唯一实现 ...
- 关于SQL语句中的distinct和group by
两种都能实现去重功能.区别: distinct只是将重复的行从结果中出去: group by是按指定的列分组,一般这时在select中会用到聚合函数. distinct是把不同的记录显示出来 grou ...