【bzoj3218】a+b Problem 最小割+主席树

数据范围:$n≤5000$,$a,l,r≤10^9$,$b,w,p≤2\times 10^5$。
我们考虑一种暴力的最小割做法:
首先令$sum=\sum\limits_{i=1}^{n} b_i+w_i$
我们建一个图:
$S->i$,边权为$w_i$
$i->T$,边权为$b_i$
$i->i'$,边权为$p_i$
$j->i'$,边权为$∞$,(这里的i和j需要满足题目中的i,j限制)
然后我们对这个图跑一遍最小割,将$sum$减去这个值输出就是答案了。
这么建图总共需要$2n+2$个点,$O(n^2)$条边
#include<bits/stdc++.h>
#define M 1000005
#define N 150005
#define INF 19890604
using namespace std; struct edge{int u,v,next;}e[M]={}; int head[N]={},use=;
void add(int x,int y,int z){e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use++;}
void ADD(int x,int y,int z){add(x,y,z); add(y,x,);} int dis[N]={},S,T; queue<int> q; bool bfs(){
memset(dis,,sizeof(dis));
q.push(S); dis[S]=;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=head[u];~i;i=e[i].next)
if(e[i].v&&dis[e[i].u]==){
dis[e[i].u]=dis[u]+;
q.push(e[i].u);
}
}
return dis[T];
} int dfs(int x,int flow){
if(x==T) return flow; int sum=;
for(int i=head[x];~i;i=e[i].next)
if(e[i].v&&dis[x]+==dis[e[i].u]){
int k=dfs(e[i].u,min(flow,e[i].v));
e[i].v-=k; e[i^].v+=k;
sum+=k; flow-=k;
if(flow==) return sum;
}
if(flow==) dis[x]=-;
return sum;
} int dinic(){
int res=;
while(bfs())
res+=dfs(S,<<);
return res;} int n,sum=;
int a[N]={},b[N]={},w[N]={},l[N]={},r[N]={},p[N]={},ok[N]={}; int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d%d",a+i,b+i,w+i,l+i,r+i,p+i);
sum+=b[i]+w[i];
}
S=,T=*n+;
memset(head,-,sizeof(head));
for(int i=;i<=n;i++) ADD(S,i,w[i]),ADD(i,T,b[i]),ADD(i+n,i,p[i]);
for(int i=;i<=n;i++) for(int j=;j<i;j++)
if(l[i]<=a[j]&&a[j]<=r[i])
ADD(j,i+n,INF);
cout<<sum-dinic()<<endl;
}
暴力
然后这个做法显然是会MLE的
我们发现原先的限制条件相当于在二维平面上框出一个允许的区间。
对于这种约束,我们可以用主席树来实现约束。
然后随便搞一搞就没了,注意细节。
#include<bits/stdc++.h>
#define M 400000
#define INF 19890604
using namespace std; struct edge{int u,v,next;}e[M]={}; int head[M]={},use=;
void add(int x,int y,int z){e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use++;}
void ADD(int x,int y,int z){add(x,y,z); add(y,x,);} int dis[M]={},S,T; queue<int> q; bool bfs(){
memset(dis,,sizeof(dis));
q.push(S); dis[S]=;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=head[u];~i;i=e[i].next)
if(e[i].v&&dis[e[i].u]==){
dis[e[i].u]=dis[u]+;
q.push(e[i].u);
}
}
return dis[T];
} int dfs(int x,int flow){
if(x==T) return flow; int sum=;
for(int i=head[x];~i;i=e[i].next)
if(e[i].v&&dis[x]+==dis[e[i].u]){
int k=dfs(e[i].u,min(flow,e[i].v));
e[i].v-=k; e[i^].v+=k;
sum+=k; flow-=k;
if(flow==) return sum;
}
if(flow==) dis[x]=-;
return sum;
} int dinic(){int res=; while(bfs()) res+=dfs(S,<<); return res;} int c[M]={},a[M]={},b[M]={},w[M]={},l[M]={},r[M]={},p[M]={};
int lc[M]={},rc[M]={},cnt,rt=,sum=,n; void updata(int x,int l,int r,int ll,int rr,int id){
if(!x) return;
if(ll<=l&&r<=rr)return ADD(x,id,INF);
int mid=(l+r)>>;
if(ll<=mid) updata(lc[x],l,mid,ll,rr,id);
if(mid<rr) updata(rc[x],mid+,r,ll,rr,id);
}
void updata(int &x,int l,int r,int id,int k){
cnt++; lc[cnt]=lc[x]; rc[cnt]=rc[x];
if(x) ADD(x,cnt,INF); x=cnt;
ADD(k,x,INF);
if(l==r) return;
int mid=(l+r)>>;
if(id<=mid) updata(lc[x],l,mid,id,k);
else updata(rc[x],mid+,r,id,k);
} int main(){
memset(head,-,sizeof(head));
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d%d",a+i,b+i,w+i,l+i,r+i,p+i);
c[i]=a[i]; sum+=b[i]+w[i];
}
sort(c+,c+n+);
for(int i=;i<=n;i++){
a[i]=lower_bound(c+,c+n+,a[i])-c;
l[i]=lower_bound(c+,c+n+,l[i])-c;
r[i]=upper_bound(c+,c+n+,r[i])-c-;
}
S=; T=*n+; cnt=*n+;
for(int i=;i<=n;i++){
ADD(S,i,w[i]);
ADD(i,T,b[i]);
ADD(i+n,i,p[i]);
if(l[i]<=r[i]) updata(rt,,n,l[i],r[i],i+n);
updata(rt,,n,a[i],i);
}
cout<<sum-dinic()<<endl;
}
【bzoj3218】a+b Problem 最小割+主席树的更多相关文章
- BZOJ3218 UOJ#77 A+B Problem(最小割+主席树)
竟然在BZOJ上拿了Rank1太给力啦. p.s.:汗,一发这个就被一堆人在2月27号强势打脸-- 传送门(BZOJ) 传送门(UOJ) 说说这道题目吧: 首先是说说这个构图吧.因为有选择关系,我们很 ...
- bzoj3218 a+b Problem(最小割+主席树优化建边)
由于6.22博主要学测,大半时间学文化课,近期刷题量&写题解的数量会急剧下降. 这题出得挺经典的,首先一眼最小割,考虑朴素的做法:与S联通表示白色,与T联通表示黑色,S向i连流量为w[i]的边 ...
- bzoj 3218 a + b Problem(最小割+主席树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3218 [题意] 给n个格子涂白或黑色,白则wi,黑则bi的好看度,若黑格i存在: 1& ...
- [bzoj3218] a+b problem [最小割+数据结构优化建图]
题面 传送门 思路 最小割 我们首先忽略掉那个奇♂怪的限制,就有一个比较显然的最小割模型: 建立源点$S$和汇点$T$ 对于每个元素$i$建立一个点$i$,连边$<S,i,w[i]>$和$ ...
- bzoj3218 a + b Problem(网络流+主席树)
$ans=\sum_{color_i=black}\ b_i+\sum_{color_i=white}\ w_i-\sum_{i=abnormal}\ p_i$ 把它转化一下 $ans=\sum_{i ...
- 【BZOJ-3218】a+b Problem 最小割 + 可持久化线段树
3218: a + b Problem Time Limit: 20 Sec Memory Limit: 40 MBSubmit: 1320 Solved: 498[Submit][Status] ...
- Yet Another Maxflow Problem CodeForces - 903G (最小割,线段树)
大意: 两个n元素集合$A$, $B$, $A_i$与$A_{i+1}$连一条有向边, $B_i$与$B_{i+1}$连一条有向边, 给定$m$条从$A_i$连向$B_j$的有向边, 每次询问修改$A ...
- P4137 Rmq Problem / mex(主席树)
传送门 思路: 直接上主席树,对于每个询问\((l,r)\),我们在第\(r\)个版本的主席树中查询最晚出现的小于\(l\)最小的数就行了. 因为答案可能为\(a_i+1\),所以我们在离散化的时候考 ...
- Codeforces 1368H - Breadboard Capacity(最小割+线段树维护矩阵乘法)
Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...
随机推荐
- poj-3177(并查集+双联通分量+Tarjan算法)
题目链接:传送门 思路: 题目要将使每一对草场之间都有至少两条相互分离的路径,所以转化为(一个有桥的连通图至少加几条边才能变为双联通图?) 先求出所有的桥的个数,同时将不同区块收缩成一个点(利用并查集 ...
- C# 中使用面向切面编程(AOP)中实践代码整洁(转)
出处:https://www.cnblogs.com/chenug/p/9848852.html 1. 前言 最近在看<架构整洁之道>一书,书中反复提到了面向对象编程的 SOLID 原则( ...
- 1.The Necessity of a Broad Education 全面教育的必要性
1.The Necessity of a Broad Education 全面教育的必要性 (1) According to a survey,which was based on the respo ...
- tflite笔记
固化模型 方法一:freeze_graph方法 把tf.train.write_graph()生成的pb文件与tf.train.saver()生成的chkp文件固化之后重新生成一个pb文件 with ...
- 百度图片http://img[0-9]\.imgtn.*?g此形式的链接图片下载方式
"""给出图片链接列表, 下载图片""" print(pic_urls) for pic_url in pic_urls: try: hos ...
- TCP/IP协议(1):各层协议帧格式
一. 1.OSI与TCP/IP对应: TCP/IP各层功能: 链路层:包括操作系统的设备驱动程序和计算机的网卡,提供底层传输服务. 网络层:为数据选择路由,在众多计算机和网络设备组成的网络中选择一 ...
- i2c设备驱动注册
Linux I2C设备驱动编写(二) 原创 2014年03月16日 23:26:50 在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_driver.i2c ...
- 用 gdb 调试 GCC 程序
Linux 包含了一个叫 gdb 的 GNU 调试程序. gdb 是一个用来调试 C 和 C++ 程序的强力调试器. 它使你能在程序运行时观察程序的内部结构和内存的使用情况. 以下是 gdb 所提供的 ...
- vue.js入门学习
可以用淘宝npm镜像 然后安装 然后初始化项目: Watch就是一个监听 v-if是如果为false就根本不在页面存在这个元素 v-show是通过display:none来控制这个元素的显示和隐藏 r ...
- 入手IntelliJ IDEA 常用配置
Idea常用设置 下载地址:https://www.jetbrains.com/idea/ 激活服务器:http://idea.iteblog.com/key.php 代码补全取消区分大小写 Inte ...