【UOJ#77】A+B Problem
题目描述
略
Sol
看到选择黑白收益不同,然后还可能有代价。
我们想到用网络流解决,并且这应该是用总可能收益-最小割得到答案。
考虑初步建图,发现那个限制可以直接 \(n^2\) 解决。
我一开始是拆了点的,但是这样没有必要,而且可能会出现一个格子黑白两种颜色都不选的情况。
所以就是黑色边从源点连出,然后白色边连到汇点。这样割掉哪条边代表不选这个颜色。
因为对于一个奇怪的格子代价只算一次,所以我们新建一个点代表这个格子变成了一个奇怪的格子。
那么对于编号小于 i 的有限制的点直接从新建点连过去一个 INF 边就行了。
这样边数显然是 \(O(n^2)\),时间不去,空间也不够。
发现连边是相当于对前缀排序后的一段区间连边,那么用主席树优化一下连边就可以了。这样点数和边数都到达 \(O(nlogn)\) 级别。
code:
#include<bits/stdc++.h>
using namespace std;
#define Set(a,b) memset(a,b,sizeof(a))
template<class T>inline void init(T&x){
x=0;char ch=getchar();bool t=0;
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);
if(t) x=-x;return;
}typedef long long ll;
const int N=1e5+200;
const int MAXN=5020;
const int M=2e6;
const int INF=2e9;
int n;
struct edge{int to,next,cap;}a[M];
int head[N],cnt=0;
int A[MAXN],B[MAXN],W[MAXN],L[MAXN],R[MAXN],P[MAXN];
int S,T;int ans=0;
inline void add(int x,int y,int z){a[cnt]=(edge){y,head[x],z};head[x]=cnt++;}
inline void add_edge(int x,int y,int z){add(x,y,z),add(y,x,0);}
int d[N],cur[N];
int stk[MAXN<<2],top=0;
queue<int> Q;
int dfs(int u,int flow){
if(u==T) return flow;
int rest=flow;
for(int v,&i=cur[u];~i;i=a[i].next) {
v=a[i].to;if(!a[i].cap||d[v]!=d[u]+1) continue;
int f=dfs(v,min(rest,a[i].cap));
if(!f) d[v]=0;
rest-=f,a[i].cap-=f,a[i^1].cap+=f;
if(!rest) break;
}return flow-rest;
}
inline bool bfs(){
while(!Q.empty()) Q.pop();Set(d,0);
d[S]=1;Q.push(S);
while(!Q.empty()) {
int u=Q.front();Q.pop();
for(int v,i=head[u];~i;i=a[i].next) {
v=a[i].to;if(!a[i].cap||d[v]) continue;
d[v]=d[u]+1;if(v==T) return 1;Q.push(v);
}
}return d[T];
}
int TAIL;
inline int Dinic(){int flow=0;while(bfs()) memcpy(cur,head,(TAIL+1)*4),flow+=dfs(S,INF);return flow;}
inline int ID(int x){return lower_bound(stk+1,stk+1+top,x)-stk;}
namespace Tree{
int cnt=0;int rt[MAXN];int ls[N],rs[N];
void LINK(int u,int l,int r,int i){
if(!u) return;
if(l>=L[i]&&r<=R[i]) return add_edge(i+n,T+u,INF);
int mid=(l+r)>>1;
if(mid>=L[i]) LINK(ls[u],l,mid,i);
if(mid< R[i]) LINK(rs[u],mid+1,r,i);
return;
}
void Insert(int&u,int l,int r,int i){
int v=++cnt;ls[v]=ls[u],rs[v]=rs[u];
if(l==r) {
add_edge(T+v,i,INF);
if(u) add_edge(T+v,T+u,INF);
u=v;return;
}u=v;
int mid=(l+r)>>1;
if(mid>=A[i]) Insert(ls[u],l,mid,i);
else Insert(rs[u],mid+1,r,i);
if(ls[u]) add_edge(T+u,T+ls[u],INF);
if(rs[u]) add_edge(T+u,T+rs[u],INF);
}
}using Tree::rt;
int main()
{
freopen("data.in","r",stdin);
init(n);Set(head,-1);
int ans=0;
for(int i=1;i<=n;++i) init(A[i]),init(B[i]),init(W[i]),init(L[i]),init(R[i]),init(P[i]),ans+=B[i]+W[i],stk[++top]=A[i],stk[++top]=L[i],stk[++top]=R[i];
sort(stk+1,stk+1+top);top=unique(stk+1,stk+1+top)-stk-1;
for(int i=1;i<=n;++i) A[i]=ID(A[i]),L[i]=ID(L[i]),R[i]=ID(R[i]);
S=0;T=(n<<1)+1;
for(int i=1;i<=n;++i) {add_edge(S,i,B[i]),add_edge(i,T,W[i]),add_edge(i,i+n,P[i]);}
for(int i=1;i<=n;++i) {
rt[i]=rt[i-1];
if(i!=1) Tree::LINK(rt[i-1],1,top,i);
Tree::Insert(rt[i],1,top,i);
}
TAIL=Tree::cnt+T;
printf("%d\n",ans-Dinic());
return 0;
}
【UOJ#77】A+B Problem的更多相关文章
- 【BZOJ3218】【UOJ#77】a + b Problem
题目 题目在这里 思路&做法 明显的最小割(其实是之前做过一道类似的题) S向每一个格子连容量为\(b_i\)的边 每一个格子向T连容量为\(w_i\)的边 对于格子\(i\)向满足条件的格子 ...
- 【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 一开始开错题了,根本就不会做. 后来发现是每次 ...
- 一本通1548【例 2】A Simple Problem with Integers
1548:[例 2]A Simple Problem with Integers 题目描述 这是一道模板题. 给定数列 a[1],a[2],…,a[n],你需要依次进行 q 个操作,操作有两类: 1 ...
随机推荐
- Wireshark 学习笔记 Lebal:Research
学习Wireshark主要是为了契合我最近做的线性激光雷达项目,主要用于抓取数据包 首先是三本书比较值得一看,第一本是清华大学出版社的,侧重教学,第二三两本是人民邮电出版社的,其中第二本是许多课程的指 ...
- ALV程序设计
ALV 全称SAP LIST VIEW, 是SAP所提供的一个强大的数据报表显示工具. ALV显示格式分为GRID及LIST两种,两者所显示数据一致, GRID模式在每个输出字段提供选择按钮,允许用 ...
- Servlet的API
(1)Servlet接口中的方法 1)init(ServletConfig arg0) 何时执行:servlet对象创建的时候执行 ServletConfig : 代表的是该servlet对象的配置信 ...
- js身份证号、电话脱敏处理(用*替换中间数据)
数字类型 certificatecodecopy = certificatecode.replace(/^(.{6})(?:\d+)(.{4})$/, "\$1****\$2") ...
- LeetCode.989-数组形式的整数做加法(Add to Array-Form of Integer)
这是悦乐书的第371次更新,第399篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第233题(顺位题号是989).对于非负整数X,X的数组形式是从左到右顺序的数字数组.例 ...
- #Java学习之路——基础阶段二(第十二篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- 【神经网络与深度学习】caffe+VS2013+Windows无GPU快速配置教程
首先来一波地址: happynear大神的第三方caffe:http://blog.csdn.net/happynear/article/details/45372231 Neil Z大神的第三方ca ...
- 微信小程序开发(一)----- 基础知识
1.什么是微信小程序 概念:小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用,体现了“用完即走”的理念,用户不需要关心是否安装太多应用的问题, ...
- vue-cli 3 ----- 项目频繁发送‘sockjs-node/info’请求
在vue-cli3跑项目时发现了这个问题,浏览器一直在频繁发送这个请求,导致联调时很不方便,而且本地开发时项目也不能实时更新. 看了网上很多的 (1) 解决方案, 大多都是直接去node_modul ...
- mysql——多表——合并查询结果
合并查询结果 合并查询结果 是将多个select语句的查询结果合并到一起 union关键字,数据库会将所有的查询结果合并到一起,然后除掉相同的记录: union all关键字,只是简单的合并到一起 前 ...