[bzoj3218] a+b problem [最小割+数据结构优化建图]
题面
思路
最小割
我们首先忽略掉那个奇♂怪的限制,就有一个比较显然的最小割模型:
建立源点$S$和汇点$T$
对于每个元素$i$建立一个点$i$,连边$<S,i,w[i]>$和$<i,T,b[i]>$
这样,割掉$<S,i>$边就表示选白色,割掉$<i,T>$边就表示选黑色,那么答案就是$\sum_{i=1}^nb[i]+w[i] - mincut$
但是现在有一个奇♂怪的限制出来了
奇♂怪的限制
这个限制,是当$i$点黑色,$j<i$点白色时出现的
那么我们考虑把这个限制对答案的影响,也用最小割的方式表现出来
我们发现,如果对于某一个点$i$,它对应的割边(就是在上面那种方法里面)是$<i,T>$,也就是它取白色的话,这个限制不会被触发
那么我们就考虑这个点的割边是$<S,i>$的情况,此时我们发现,如果我们想把这个$p[i]$也变成最小割的一部分的话,我们就要对于所有可能触发的$j$,构成一条这样的链:
$<S,i>-<i,j>-<j,T>$
但是这个中间这条,显然不能直接在$i,j$中间连边,因为这样无法体现出链的特性
我们考虑这样的一个方法,来分开黑白割的情况
我们对于每个点,新建节点$ii$,然后对于每个$ii$,连边$<ii,i,p[i]>$
对于$i$所有能够访问到的点,连边$<i,jj,inf>$,$inf$表示不可割
这样跑最小割,还是用所有的$b,w$的和来减,就是答案了
建图优化
显然这个东西直接连边的话,$n^2$的会炸
所以我们用一个主席树来优化一下建图
用所有的$i$连向对应的主席树链上的所有点,主席树上的点就横向连边(旧的往新的连),然后每个点从它覆盖的所有区间连过来
开的主席树的数组下标意义就是$a$的大小,这样方便取区间
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<cmath>
#define ll long long
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,first[200010],cnte=-1,dep[200010],cur[200010];
struct edge{
int to,next;ll w;
}a[1500010];
void add(int u,int v,ll w){
a[++cnte]=(edge){v,first[u],w};first[u]=cnte;
a[++cnte]=(edge){u,first[v],0};first[v]=cnte;
}
bool bfs(int s,int t){
int i,u,v,q[200010],head=0,tail=1;
for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
dep[s]=0;q[0]=s;
while(head<tail){
u=q[head++];
for(i=first[u];~i;i=a[i].next){
v=a[i].to;if(~dep[v]||!a[i].w) continue;
dep[v]=dep[u]+1;q[tail++]=v;
}
}
return ~dep[t];
}
int dfs(int u,int t,ll lim){
if(u==t||!lim) return lim;
int i,v,f,flow=0;
for(i=cur[u];~i;i=a[i].next){
v=a[i].to;cur[u]=i;
if(dep[v]==dep[u]+1&&(f=dfs(v,t,min(a[i].w,lim)))){
flow+=f;lim-=f;
a[i].w-=f;a[i^1].w+=f;
if(!lim) return flow;
}
}
if(lim) dep[u]=-1;
return flow;
}
ll dinic(int s,int t){
ll re=0;
while(bfs(s,t)) re+=dfs(s,t,1e12);
return re;
}
struct chairmantree{
int ch[1000010][2],cnt,root[5010];
int insert(int l,int r,int pos,int pre,int u){
int cur=++cnt;
ch[cur][0]=ch[pre][0];ch[cur][1]=ch[pre][1];
add(u,cur,1e12);
if(l==r){
if(pre) add(pre,cur,1e12);
return cur;
}
int mid=(l+r)>>1;
if(mid>=pos){
ch[cur][0]=insert(l,mid,pos,ch[pre][0],u);
if(pre) add(pre,cur,1e12);
}
else{
ch[cur][1]=insert(mid+1,r,pos,ch[pre][1],u);
if(pre) add(pre,cur,1e12);
}
return cur;
}
void check(int l,int r,int ql,int qr,int cur,int u){
if(!cur) return;
int mid=(l+r)>>1;
if(l>=ql&&r<=qr){
add(cur,u,1e12);
return;
}
if(mid>=ql) check(l,mid,ql,qr,ch[cur][0],u);
if(mid<qr) check(mid+1,r,ql,qr,ch[cur][1],u);
}
}T;
int main(){
memset(first,-1,sizeof(first));
n=read();int i,val,b,w,l,r,p;ll sum=0;
int s=0,t=200000;T.cnt=n<<1;
for(i=1;i<=n;i++){
val=read();b=read();w=read();l=read();r=read();p=read();
sum+=(ll)b+w;
add(s,i,w);add(i,t,b);add(i+n,i,p);
T.root[i]=T.insert(0,1e9,val,T.root[i-1],i);
T.check(0,1e9,l,r,T.root[i-1],i+n);
}
printf("%lld\n",sum-dinic(s,t));
}
[bzoj3218] a+b problem [最小割+数据结构优化建图]的更多相关文章
- cf786E ALT (最小割+倍增优化建图)
如果把“我全都要”看作是我全不要的话,就可以用最小割解决啦 源点S,汇点T 我们试图让每个市民作为一个等待被割断的路径 把狗狗给市民:建边(S,i,1),其中i是市民 把狗狗给守卫:建边(j,T,1) ...
- [bzoj3218]a + b Problem 网络流+主席树优化建图
3218: a + b Problem Time Limit: 20 Sec Memory Limit: 40 MBSubmit: 2229 Solved: 836[Submit][Status] ...
- bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能 ...
- 一个神秘的oj2587 你猜是不是dp(线段树优化建图)
哇 这难道不是happiness的翻版题嘛? 从\(S\)向一个点连染成白色的收益 从这个点向\(T\)连染成黑色的收益 对于额外的收益,建一个辅助点,跟区间内的每个点连\(inf\),然后向S/T, ...
- [SDOI2017]天才黑客[最短路、前缀优化建图]
题意 一个 \(n\) 点 \(m\) 边的有向图,还有一棵 \(k\) 个节点的 trie ,每条边上有一个字符串,可以用 trie 的根到某个节点的路径来表示.每经过一条边,当前携带的字符串就会变 ...
- CF1007D. Ants(树链剖分+线段树+2-SAT及前缀优化建图)
题目链接 https://codeforces.com/problemset/problem/1007/D 题解 其实这道题本身还是挺简单的,这里只是记录一下 2-SAT 的前缀优化建图的相关内容. ...
- poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙
/** 题目:poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙 链接:http://poj.org/problem?id=3680 题意:给定n个区间,每个区间(ai,bi ...
- 【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra
题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ...
- BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流
BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流 Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1 ...
随机推荐
- mpvue项目中安装weui
观察一下发现,mpvue项目打包css的规律是:根组件App.vue里的style样式全部打包到 dist / static / css / app.wxss .. 参照微信小程序的原生引入使 ...
- udp回显客户端发送的数据
这里让客户端给服务端发送的数据被服务端自动发回来 客户端: import socket client_socket = socket.socket(socket.AF_INET, socket.SOC ...
- sqlite的sql常用语句(笔记)
1.复制一张表并重命名 比如已经创建好一个表 表名为"28165" 复制这个表. CREATE TABLE [33150] AS SELECT * FROM [28165] 2.根 ...
- Linux用户与组管理命令
1.列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可. who | cut -d" " -f1 | sort -u 或 who | cut -d ...
- xml的应用与dtd约束
1.xml的应用 *不同的系统之间的传输数据(qq消息传输) *用来表示生活中有关系的数据(省市区的包含关系) *经常用在文件配置 **比如现在连接数据库,肯定知道数据库的名称和密码及用户名. ...
- 一行代码搞定checkbox全选和全不选
<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...
- linux 下chown改变隐藏文件夹
chown 在更改隐藏文件的时候,发现无法更改其用户组,如果需要将隐藏文件夹也做一个更改,那么需要加上-h选项. sudo chown ai/node/ * -hR 使用以上命令即可.
- 裸机——RTC
1. 首先晓得RTC的基本知识 RTC被划分到timer,但RTC是面向时间点的. 如果按照定时器的思路去思考,那么应该考虑 时间周期 和 计数值. RTC 不是面向时间点的,所以略有不同, 时间周期 ...
- 移动端的拖拽排序在react中实现 了解一下
最近做一个拖拽排序的功能找了好几个有一个步骤简单,结合redux最好不过了,话不多说上代码 第一步: npm install react-draggable-tags --save 第二步 sort. ...
- 2 实现第一个Django网站 博客
-1.理解上下文 render()渲染 request url传来的reuqest x.html 制定返回的模板名称 context 上下文 数据库中 替换数据 0.大框架 1.创建模板 (1 ...