[BZOJ 3218] A + B Problem 【可持久化线段树 + 网络流】
题目连接:BZOJ - 3218
题目分析
题目要求将 n 个点染成黑色或白色,那么我们可以转化为一个最小割模型。
我们规定一个点 i 最后属于 S 集表示染成黑色,属于 T 集表示染成白色,那么对于每个点 i 就要连边 (S, i, B[i]) 和 (i, T, W[i])。
这样,如果一个点属于 S 集,就要割掉与 T 相连的边,就相当于失去了染成白色的收益。
我们再来考虑 “奇怪的点”,一个点 i 变成奇怪的点的条件是:i 是黑色且存在一个白色点 j 满足 j < i && L[i] <= A[j] <= R[i]。
对于这一点,我们可以对于每个点 i 再添加一个点 n + i ,连边 (i, n + i, P[i]) ,对于每个符合条件的 j ,连边 (n + i, j, INF) 。
这样,就实现了,只要有 j 是白色,那么 j 与 T 相连,n + i 就一定与 T 相连,而如果 i 是与 S 相连,就一定要割掉 (i -> n + i) 的价值为 P[i] 的边。
然而这样的边数可以达到 n^2 级别,是不能通过全部数据的。
我们可以考虑用线段树优化网络流的连边。
我们建一棵权值线段树(对所有的 L, R, A 离散化后会节省时间和空间),从每个 j 对应的 A[j] 节点向 j 连 INF 边,从线段树节点向这个节点的儿子节点连 INF 边,对于每个 i ,就再线段树中找到对应的 [L[i], R[i]] 区间,从 n + i 向组成这些区间的节点连 INF 边。
然而我们还没有考虑 j < i 的限制,那么使用可持久化线段树就可以了。
需要注意的一点是,对于第 i 个位置,插入 A[i] 时,是依托 i - 1 的线段树版本建立的,如果发现在 i - 1 版本的线段树中已经存在权值为 A[i] 的节点,那么就从 i 版本表示 A[i] 单点的线段树节点(设为Now)向 i - 1 版本的线段树中表示 A[i] 单点的线段树节点 (设为 Last)连边 (Now, Last, INF) 。
代码
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map> using namespace std; const int MaxN = + , MaxNode = + , MaxM = + , INF = ; map<int, int> M; int n, Top, Tot, S, T, HN, Index, Ans;
int A[MaxN], B[MaxN], W[MaxN], L[MaxN], R[MaxN], Pi[MaxN], Arr[MaxN * ];
int Root[MaxN], Son[MaxNode][], d[MaxNode], Num[MaxNode]; struct Edge
{
int u, v, w;
Edge *Next, *Other;
} E[MaxM * ], *P = E, *Point[MaxNode], *Last[MaxNode]; inline void AddEdge(int x, int y, int z)
{
Edge *Q = ++P; ++P;
P -> u = x; P -> v = y; P -> w = z;
P -> Next = Point[x]; Point[x] = P; P -> Other = Q;
Q -> u = y; Q -> v = x; Q -> w = ;
Q -> Next = Point[y]; Point[y] = Q; Q -> Other = P;
} void Insert(int &x, int Lt, int s, int t, int Pos, int Idx)
{
if (x == ) x = ++Index;
if (s == t)
{
AddEdge(Tot + x, Idx, INF);
if (Lt) AddEdge(Tot + x, Tot + Lt, INF);
return;
}
int m = (s + t) >> ;
if (Pos <= m)
{
Son[x][] = Son[Lt][];
Insert(Son[x][], Son[Lt][], s, m, Pos, Idx);
}
else
{
Son[x][] = Son[Lt][];
Insert(Son[x][], Son[Lt][], m + , t, Pos, Idx);
}
if (Son[x][]) AddEdge(Tot + x, Tot + Son[x][], INF);
if (Son[x][]) AddEdge(Tot + x, Tot + Son[x][], INF);
} void Link(int x, int s, int t, int l, int r, int Idx)
{
if (l <= s && r >= t)
{
AddEdge(n + Idx, Tot + x, INF);
return;
}
int m = (s + t) >> ;
if (Son[x][] && l <= m) Link(Son[x][], s, m, l, r, Idx);
if (Son[x][] && r >= m + ) Link(Son[x][], m + , t, l, r, Idx);
} inline int gmin(int a, int b) {return a < b ? a : b;} int DFS(int Now, int Flow)
{
if (Now == T) return Flow;
int ret = ;
for (Edge *j = Last[Now]; j; j = j -> Next)
{
if (j -> w && d[Now] == d[j -> v] + )
{
int p = DFS(j -> v, gmin(j -> w, Flow - ret));
j -> w -= p; j -> Other -> w += p; ret += p;
if (ret == Flow) return ret;
}
}
if (d[S] >= Tot) return ret;
if (--Num[d[Now]] == ) d[S] = Tot;
++Num[++d[Now]];
Last[Now] = Point[Now];
return ret;
} int main()
{
scanf("%d", &n);
Top = ;
for (int i = ; i <= n; ++i)
{
scanf("%d%d%d%d%d%d", &A[i], &B[i], &W[i], &L[i], &R[i], &Pi[i]);
Arr[++Top] = A[i]; Arr[++Top] = L[i]; Arr[++Top] = R[i];
}
sort(Arr + , Arr + Top + );
HN = ;
M.clear();
for (int i = ; i <= Top; ++i)
{
if (i != && Arr[i] == Arr[i - ]) continue;
M[Arr[i]] = ++HN;
}
for (int i = ; i <= n; ++i)
{
A[i] = M[A[i]];
L[i] = M[L[i]]; R[i] = M[R[i]];
}
memset(Root, , sizeof(Root));
S = n * + ; T = n * + ;
Tot = n * + ;
Index = ;
Ans = ;
for (int i = ; i <= n; ++i)
{
AddEdge(S, i, B[i]);
AddEdge(i, T, W[i]);
AddEdge(i, n + i, Pi[i]);
Ans += B[i] + W[i];
}
for (int i = ; i <= n; ++i)
{
if (i > ) Link(Root[i - ], , HN, L[i], R[i], i);
Insert(Root[i], Root[i - ], , HN, A[i], i);
}
Tot = Tot + Index;
memset(d, , sizeof(d));
memset(Num, , sizeof(Num)); Num[] = Tot;
for (int i = ; i <= Tot; ++i) Last[i] = Point[i];
while (d[S] < Tot) Ans -= DFS(S, INF);
printf("%d\n", Ans);
return ;
}
[BZOJ 3218] A + B Problem 【可持久化线段树 + 网络流】的更多相关文章
- BZOJ 3218 A + B Problem (可持久化线段树+最小割)
做法见dalao博客 geng4512的博客, 思路就是用线段树上的结点来进行区间连边.因为有一个只能往前面连的限制,所以还要可持久化.(duliu) 一直以来我都是写dinicdinicdinic做 ...
- [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)
[BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...
- UOJ#77. A+B Problem [可持久化线段树优化建边 最小割]
UOJ#77. A+B Problem 题意:自己看 接触过线段树优化建图后思路不难想,细节要处理好 乱建图无果后想到最小割 白色和黑色只能选一个,割掉一个就行了 之前选白色必须额外割掉一个p[i], ...
- BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)
BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...
- 【BZOJ3218】a + b Problem 可持久化线段树优化建图
[BZOJ3218]a + b Problem 题解:思路很简单,直接最小割.S->i,容量为Bi:i->T,容量为Wi:所有符合条件的j->new,容量inf:new->i, ...
- BZOJ 3653: 谈笑风生(DFS序+可持久化线段树)
首先嘛,还是太弱了,想了好久QAQ 然后,这道题么,明显就是求sigma(size[x]) (x是y的儿子且层树小于k) 然后就可以发现:把前n个节点按深度建可持久化线段树,就能用前缀和维护了 其实不 ...
- bzoj 4504: K个串 可持久化线段树+堆
题目: Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想 ...
- bzoj 3514: GERALD07加强版 lct+可持久化线段树
题目大意: N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 题解: 这道题考试的时候没想出来 于是便爆炸了 结果今天下午拿出昨天准备的题表准备做题的时候 题表里就有这题 ...
- BZOJ 3524 [Poi2014]Couriers(可持久化线段树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3524 [题目大意] 给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个 ...
随机推荐
- Velocity源码分析
velocity模板渲染的步骤: 1) 首先初始化启动Velocity引擎,可以通过Velocity.init()或者新建VelocityEngine类,并调用其中的init()方法: 2) 创建一个 ...
- 通过strace 监控 fdatasync
通过strace 监控 Redis AOF文件的系统调用 Redis中主要的AOF设置 「appendonly yes」 开启每次更新操作后进行日志记录 「appendfilename appendo ...
- CentOS下MySQL 5.7编译安装
CentOS下MySQL 5.7编译安装 文章目录 安装依赖包 下载相应源码包 添加mysql用户 预编译 编译安装 启动脚本,设置开机自启动 /etc/my.cnf,仅供参考 初始化数据库 设置 ...
- PureMVC(JS版)源码解析(八):Proxy类
前面,我们讲了与视图相关联的Mediator类,接下来我们讲讲与数据相关联的Proxy类. 关于Proxy类的作用,在Proxy类源码中,有这么一段注释: * In PureMVC, Proxy c ...
- Go语言学习资料汇总
网站: Go语言官网(访问)(中文镜像) Go语言中文网(访问) Go编译器(访问) Go语言中国社区(访问) golanghome(访问) GoLang中国(访问) Gopher Academic( ...
- CentOS 6.7平台Hadoop 1.2.1环境搭建
本教程使用Vultr的VPS搭建,主要实现HDFS和MapReduce两个功能. master.hadoop - 45.32.90.100 slave1.hadoop - 45.32.92.47 sl ...
- 逻辑回归应用之Kaggle泰坦尼克之灾(转)
正文:14pt 代码:15px 1 初探数据 先看看我们的数据,长什么样吧.在Data下我们train.csv和test.csv两个文件,分别存着官方给的训练和测试数据. import pandas ...
- C#实现动态网站伪静态,使seo更友好
本教程将使用Visual Studio 2013手把手教你实现webform动态页面的伪静态.本教程配套的C#源码工程可通过我的github下载.地址:https://github.com/shell ...
- IPX/SPX
转自百度百科 方便阅读 IPX/SPX 目 录 1英文原义 2中文释义 3IPX协议 3.1 说明 3.2 应用 4SPX协议 4.1 说明 4.2 应用 1英文原义 IPX/SPX 2中 ...
- wordpress 后台显示空白现象
简单的说两句,出现此种现象的因素可能在于主题或者插件再或者是因为(恶意)插件(误更改)更改了某个重要的文件出现错误.本次我遇到的是插件的错误,具体是什么错误,我也没有去深究,重要的是结果! 使用排查的 ...