【BZOJ3218】【UOJ#77】a + b Problem
题目
思路&做法
明显的最小割(其实是之前做过一道类似的题)
S向每一个格子连容量为\(b_i\)的边
每一个格子向T连容量为\(w_i\)的边
对于格子\(i\)向满足条件的格子\(j(1 \leq j < i, l_i \leq a_j \leq r_i)\)连容量为\(p_i\)的边
但是考虑到这题恶心的数据范围, 这样做很明显会TLE。
算法的瓶颈在第三步。我们发现\(j\)的范围看起来像是一个像二维偏序的东西, 于是便可以用主席树来优化一下, 对于每个节点\(i\)新建一个节点\(k\),由i向k连容量为\(p_i\)的边, 由\(k\)向主席树中\(j\)的范围的对应的节点连容量为\(inf\)的边。
代码
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int INF = 0x7F7F7F7F;
const int N = 50010, M = 1450010;
struct edge
{ int from, to, flow, cap;
edge() { }
edge(int _1, int _2, int _3, int _4) : from(_1), to(_2), flow(_3), cap(_4) { }
};
struct Dinic
{ edge edges[M];
int head[165022], nxt[M], tot;
int L, R;
inline void init()
{ memset(head, -1, sizeof(head));
tot = 0;
}
void add_edge(int x, int y, int z)
{ edges[tot] = edge(x, y, 0, z);
nxt[tot] = head[x];
head[x] = tot++;
edges[tot] = edge(y, x, 0, 0);
nxt[tot] = head[y];
head[y] = tot++;
}
int s, t;
int d[165022];
bool bfs()
{ memset(d, -1, sizeof(d));
queue<int> q;
d[s] = 0;
q.push(s);
while (!q.empty())
{ int x = q.front(); q.pop();
for (int i = head[x]; ~i; i = nxt[i])
{ edge & e = edges[i];
if (e.cap > e.flow && d[e.to] == -1)
{ d[e.to] = d[x] + 1;
q.push(e.to);
}
}
}
return d[t] != -1;
}
int cur[165022];
int dfs(int x, int a)
{ if (x == t || a == 0) return a;
int flow = 0, f;
for (int & i = cur[x]; ~i; i = nxt[i])
{ edge & e = edges[i];
if (d[e.to] == d[x] + 1 && (f = dfs(e.to, min(a, e.cap-e.flow))) > 0)
{ e.flow += f;
edges[i^1].flow -= f;
a -= f;
flow += f;
if (a == 0) break;
}
}
return flow;
}
int maxflow(int _s, int _t)
{ s = _s, t = _t;
int flow = 0;
while (bfs())
{ for (int i = L; i <= R; i++)
cur[i] = head[i];
flow += dfs(s, INF);
}
return flow;
}
} dinic;
int n;
int root[N];
struct SegmentTree
{ int ls[N*20], rs[N*20], sz;
void update(int & cur, int pre, int l, int r, int p, int node)
{ cur = ++sz;
if (l == r)
{ if (pre) dinic.add_edge(cur, pre, INF);
dinic.add_edge(cur, node, INF);
return;
}
ls[cur] = ls[pre];
rs[cur] = rs[pre];
int mid = (l + r) >> 1;
if (p <= mid)
update(ls[cur], ls[pre], l, mid, p, node);
else
update(rs[cur], rs[pre], mid+1, r, p, node);
dinic.add_edge(cur, ls[cur], INF);
dinic.add_edge(cur, rs[cur], INF);
}
void link(int cur, int l, int r, int ql, int qr, int node)
{ if (ql == l && qr == r)
dinic.add_edge(node, cur, INF);
else
{ int mid = (l + r) >> 1;
if (qr <= mid)
link(ls[cur], l, mid, ql, qr, node);
else if (ql > mid)
link(rs[cur], mid+1, r, ql, qr, node);
else
link(ls[cur], l, mid, ql, mid, node),
link(rs[cur], mid+1, r, mid+1, qr, node);
}
}
} st;
int a[N], w[N], b[N], L[N], R[N], p[N];
int num[N], total;
int main()
{ scanf("%d", &n);
for (int i = 1; i <= n; i++)
{ scanf("%d %d %d %d %d %d", &a[i], &b[i], &w[i], &L[i], &R[i], &p[i]);
num[++total] = a[i];
num[++total] = L[i];
num[++total] = R[i];
}
sort(num+1, num+total+1);
total = unique(num+1, num+total+1) - num - 1;
for (int i = 1; i <= n; i++)
{ a[i] = lower_bound(num+1, num+1+total, a[i]) - num;
L[i] = lower_bound(num+1, num+1+total, L[i]) - num;
R[i] = lower_bound(num+1, num+1+total, R[i]) - num;
}
int ans = 0;
dinic.init();
int S = n + n + 1, T = n + n + 2;
st.sz = n + n + 2;
for (int i = 1; i <= n; i++)
{ dinic.add_edge(S, i, b[i]);
dinic.add_edge(i, T, w[i]);
dinic.add_edge(i, i+n, p[i]);
if (i > 1)
st.link(root[i-1], 1, total, L[i], R[i], i+n);
st.update(root[i], root[i-1], 1, total, a[i], i);
ans += b[i] + w[i];
}
dinic.L = 0, dinic.R = st.sz;
ans -= dinic.maxflow(S, T);
printf("%d\n", ans);
}
/*
10
0 1 7 3 9 2
7 4 0 9 10 5
1 0 4 2 10 2
7 9 1 5 7 2
6 3 5 3 6 2
6 6 4 1 8 1
6 1 6 0 6 5
2 2 5 0 9 3
5 1 3 0 2 5
5 6 7 1 1 2
*/
【BZOJ3218】【UOJ#77】a + b Problem的更多相关文章
- 【UOJ#77】A+B Problem
传送门 题目描述 略 Sol 看到选择黑白收益不同,然后还可能有代价. 我们想到用网络流解决,并且这应该是用总可能收益-最小割得到答案. 考虑初步建图,发现那个限制可以直接 \(n^2\) 解决. 我 ...
- 【UOJ#236】[IOI2016]railroad(欧拉回路,最小生成树)
[UOJ#236][IOI2016]railroad(欧拉回路,最小生成树) 题面 UOJ 题解 把速度看成点,给定的路段看成边,那么现在就有了若干边,然后现在要补上若干边,以及一条\([inf,\) ...
- 【UOJ#177】欧拉回路
[UOJ#177]欧拉回路 题面 UOJ 题解 首先图不连通就没啥好搞的了. 对于无向图而言,每个点度数为偶数. 对于有向图而言,每个点入度等于出度. 然后就是一本通上有的做法,直接\(dfs\)一遍 ...
- 【UOJ#311】【UNR #2】积劳成疾(动态规划)
[UOJ#311][UNR #2]积劳成疾(动态规划) UOJ Solution 考虑最大值分治解决问题.每次枚举最大值所在的位置,强制不能跨过最大值,左右此时不会影响,可以分开考虑. 那么设\(f[ ...
- 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)
[UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...
- 【UOJ#246】套路(动态规划)
[UOJ#246]套路(动态规划) 题面 UOJ 题解 假如答案的选择的区间长度很小,我们可以做一个暴力\(dp\)计算\(s(l,r)\),即\(s(l,r)=min(s(l+1,r),s(l,r- ...
- 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)
[UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ...
- 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)
[UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...
- 【UOJ#275】组合数问题(卢卡斯定理,动态规划)
[UOJ#275]组合数问题(卢卡斯定理,动态规划) 题面 UOJ 题解 数据范围很大,并且涉及的是求值,没法用矩阵乘法考虑. 发现\(k\)的限制是,\(k\)是一个质数,那么在大组合数模小质数的情 ...
随机推荐
- 【Oracle】数据迁移工具(2):Data Dump
Data Dump 使用命令行IMPDP/EXPDP实现导入导出表.schema.表空间及数据库.IMPDP/EXPDP命令行中可以加入以下选项,来实现更细粒度的导入导出. IMPDP/EXPDP和I ...
- 参加EMCL感想
ECML,全名为欧洲机器学习会议,European Conference on Machine Learning 原文链接:http://blog.sina.com.cn/s/blog_59388e2 ...
- mysql 5.6 中 explicit_defaults_for_timestamp参数
mysql 5.6 中 explicit_defaults_for_timestamp参数 一: 官方文档中关于explicit_defaults_for_timestamp参数说明如下: expli ...
- Quartz+Topshelf 作业
小记: 引用Quartz.Topshelf.Topshelf.Quartz 使用方法: http://www.cnblogs.com/mushroom/p/4952461.html http://ww ...
- Vim入门基础知识集锦
1. 简介 Vim(Vi[Improved])编辑器是功能强大的跨平台文本文件编辑工具,继承自Unix系统的Vi编辑器,支持Linux/Mac OS X/Windows系统,利用它可以建立.修 ...
- matlab学习checkbox使用
添加radiobutton1和checkbox2控件以及两个edittextbox控件 %得到控件的值var=get(handles.kj2,'value');%将数值显示到文本框中,将得到的数值转换 ...
- position:搜索框显示历史浏览记录
absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位. 元素的位置通过 "left", "top", "righ ...
- 日记——OI历程
学OI也一年多了(2015.12-),一直没学出个像样的东西.相比dalao们,我还是弱爆了. ljj,qyf,yyf三位三区dalao. xxy,myj两位三区学长dalao. 稍微总结一下前一段时 ...
- [Ynoi2016]镜中的昆虫
题目大意: 给定一个序列,有2个操作: 1. 区间覆盖.2. 区间数颜色. 解题思路: 珂朵莉树+树套树. 看到区间覆盖当然想到珂朵莉树然而这是Ynoi 所以我们得优化掉珂朵莉树那个暴力过程. 考虑对 ...
- PAT 1065. A+B and C
Given three integers A, B and C in [-263, 263], you are supposed to tell whether A+B > C. Input S ...