[BZOJ3128]a+b Problem


题解
最小割+主席树优化建图
首先看到每个点只有\(0/1\)两种状态就想到最小割
然后由于有一个限制是点\(i\)是黑点且有符合条件的白点就会减去\(p_i\)
所以我们将\(S\)集合设为黑点集合,\(T\)集合设为白点集合
然后\(S\to i\)流量为\(b_i\) , \(i\to T\)流量为\(w_i\)
然后我们就需要考虑如果一个点选择了黑点那么就要去判断有没有符合条件的白点
所以我们对每个\(i\)新建一个\(i'\)
然后\(i\to i'\)连流量为\(p_i\)的边
\(i'\)向符合条件的\(j\)连流量为\(INF\)的边
由于是求最大值,所以答案就是\(\sum_{b_i+w_i}-\)最小割
这样建图的最小割就可以起到自动分类讨论的作用
例如如果\(i\)为黑点,\(j\)为白点,那么就会产生\(-p_i\)的贡献
这样的话如果我们实际选择了\(i\)为黑点,\(j\)为白点
那么这一路的流量就是\(w_i+b_j+\min(b_i-w_i,p_i,w_j-b_j)\)
这样就自动的起到了分类讨论的作用
然后我们发现一个黑点对于符合条件的白点的要求是一个二维的限制
所以可以考虑主席树优化建图
跟线段树优化建图比较类似
就是在继承上一棵主席树的时候两棵主席树之间要互相连一条边
void insert() {
t[++tot] = t[now] ;
add_edge(tot , now) ; /*注意这里要连边*/
now = tot ;
}
代码
#include<map>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
# define ls (t[now].lsn)
# define rs (t[now].rsn)
const int M = 500005 ;
const int N = 5050 ;
const int INF = 1e9 ;
using namespace std ;
inline int read() {
char c = getchar() ; int x = 0 , w = 1 ;
while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
return x*w ;
}
map < int , int > mp ;
int n , tot , S , T , cnt ;
int num = 1 , hea[M] , ans ;
int rt[N] , s[N] , suc[N] , idk[N] , d[M] ;
int a[N] , b[N] , w[N] , lp[N] , rp[N] , p[N] ;
struct E { int nxt , to , dis ; } edge[M * 5] ;
struct Node { int lsn , rsn ; } t[M] ;
inline void Insert_edge(int from , int to , int dis) {
edge[++num].nxt = hea[from] ; edge[num].to = to ;
edge[num].dis = dis ; hea[from] = num ;
}
inline void add_edge(int u , int v , int w) {
Insert_edge(u , v , w) ;
Insert_edge(v , u , 0) ;
}
inline int Gid(int x) {
int l = 1 , r = cnt , ret = 0 , mid ;
while(l <= r) {
mid = (l + r) >> 1 ;
if(suc[mid] <= x) l = mid + 1 , ret = mid ;
else r = mid - 1 ;
}
return ret ;
}
void Insert(int id , int x , int l , int r , int &now) {
t[++tot] = t[now] ; add_edge(tot , now , INF) ; now = tot ;
if(l == r) { add_edge(now , id , INF) ; return ; }
int mid = (l + r) >> 1 ;
if(mid >= x) Insert(id , x , l , mid , ls) ;
else Insert(id , x , mid + 1 , r , rs) ;
if(ls) add_edge(now , ls , INF) ;
if(rs) add_edge(now , rs , INF) ;
}
void Add(int id , int L , int R , int l , int r , int now) {
if(now <= n) return ;
if(l >= L && r <= R) { add_edge(id , now , INF) ; return ; }
int mid = (l + r) >> 1 ;
if(mid >= R) Add(id , L , R , l , mid , ls) ;
else if(mid < L) Add(id , L , R , mid + 1 , r , rs) ;
else Add(id , L , mid , l , mid , ls) , Add(id , mid + 1 , R , mid + 1 , r , rs) ;
}
inline bool bfs() {
queue < int > q ; q.push(S) ;
memset(d , 0 , sizeof(d)) ; d[S] = 1 ;
while(!q.empty()) {
int u = q.front() ; q.pop() ;
for(int i = hea[u] ; i ; i = edge[i].nxt) {
int v = edge[i].to ;
if(!d[v] && edge[i].dis > 0) {
d[v] = d[u] + 1 ;
q.push(v) ; if(v == T) return true ;
}
}
}
return d[T] ;
}
int dfs(int u , int dis) {
if(u == T || !dis) return dis ; int sum = 0 ;
for(int i = hea[u] ; i ; i = edge[i].nxt) {
int v = edge[i].to ;
if(d[v] == d[u] + 1 && edge[i].dis > 0) {
int diss = dfs(v , min(dis , edge[i].dis)) ;
if(diss > 0) {
edge[i].dis -= diss ; edge[i ^ 1].dis += diss ;
dis -= diss ; sum += diss ; if(!dis) break ;
}
}
}
if(!sum) d[u] = -1 ; return sum ;
}
inline int dinic() {
int tmp = 0 ;
while(bfs())
tmp += dfs(S , INF) ;
return tmp ;
}
int main() {
n = read() ;
for(int i = 1 ; i <= n ; i ++) {
a[i] = read() ; b[i] = read() ; w[i] = read() ;
lp[i] = read() ; rp[i] = read() ; p[i] = read() ;
add_edge(S , ++tot , b[i]) ;
s[i] = a[i] ; ans += b[i] + w[i] ;
}
rt[0] = tot ;
sort(s + 1 , s + n + 1) ;
for(int i = 1 ; i <= n ; i ++) {
if(i == 1 || s[i] != s[i - 1]) ++ cnt ;
mp[s[i]] = cnt ; suc[cnt] = s[i] ;
}
for(int i = 1 ; i <= n ; i ++)
a[i] = mp[a[i]] ;
for(int i = 1 ; i <= n ; i ++) {
rt[i] = rt[i - 1] ;
Insert(i , a[i] , 0 , cnt , rt[i]) ;
}
for(int i = 1 ; i <= n ; i ++) {
idk[i] = ++ tot ;
add_edge(i , idk[i] , p[i]) ;
}
T = tot + 1 ;
for(int i = 1 ; i <= n ; i ++)
add_edge(i , T , w[i]) ;
suc[0] = -1 ;
for(int i = 1 , l , r ; i <= n ; i ++) {
l = Gid(lp[i]) , r = Gid(rp[i]) ;
if(lp[i] != suc[l]) ++ l ;
if(l > r) continue ;
Add(idk[i] , l , r , 0 , cnt , rt[i - 1]) ;
}
printf("%d\n",ans - dinic()) ;
return 0 ;
}
[BZOJ3128]a+b Problem的更多相关文章
- 1199 Problem B: 大小关系
求有限集传递闭包的 Floyd Warshall 算法(矩阵实现) 其实就三重循环.zzuoj 1199 题 链接 http://acm.zzu.edu.cn:8000/problem.php?id= ...
- No-args constructor for class X does not exist. Register an InstanceCreator with Gson for this type to fix this problem.
Gson解析JSON字符串时出现了下面的错误: No-args constructor for class X does not exist. Register an InstanceCreator ...
- C - NP-Hard Problem(二分图判定-染色法)
C - NP-Hard Problem Crawling in process... Crawling failed Time Limit:2000MS Memory Limit:262144 ...
- Time Consume Problem
I joined the NodeJS online Course three weeks ago, but now I'm late about 2 weeks. I pay the codesch ...
- Programming Contest Problem Types
Programming Contest Problem Types Hal Burch conducted an analysis over spring break of 1999 and ...
- hdu1032 Train Problem II (卡特兰数)
题意: 给你一个数n,表示有n辆火车,编号从1到n,入站,问你有多少种出站的可能. (题于文末) 知识点: ps:百度百科的卡特兰数讲的不错,注意看其参考的博客. 卡特兰数(Catalan):前 ...
- BZOJ2301: [HAOI2011]Problem b[莫比乌斯反演 容斥原理]【学习笔记】
2301: [HAOI2011]Problem b Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 4032 Solved: 1817[Submit] ...
- [LeetCode] Water and Jug Problem 水罐问题
You are given two jugs with capacities x and y litres. There is an infinite amount of water supply a ...
- [LeetCode] The Skyline Problem 天际线问题
A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...
随机推荐
- 在springboot中使用Mybatis Generator的两种方式
介绍 Mybatis Generator(MBG)是Mybatis的一个代码生成工具.MBG解决了对数据库操作有最大影响的一些CRUD操作,很大程度上提升开发效率.如果需要联合查询仍然需要手写sql. ...
- javascrip中ajax
移动端对加载速度要求比较高,由于jquery插件有270多k,无形中增加加载的速度,下面整理一下原生js中ajax: 先了解ajax的基础知识 (1)XMLHttpRequest 对象 XMLHttp ...
- 信息发布员和频道管理员如何查看dedecms自定义表单内容
自定义表单的管理权限,超级管理员有,而频道管理员没有.在频道管理员的权限设置选项里,找不到自定义表单这一项.怎么办呢. 刚开始想修改权限设置选项,但觉得太麻烦.是否有偷懒取巧的办法? 在频道管理员的后 ...
- 在jboss中部署可执行jar, deploy executable jar in jboss
首先,题目是个伪命题, jboss容器是不支持直接部署可执行jar包的,jar只会被加载当作lib对待.这里提供了一个小的变通方案. 今天我遇到个问题,把我们的项目中的监控模块独立成一个小项目部署,监 ...
- swoole异步redis安装前置条件和流程
---恢复内容开始--- 1.redis服务 确认redis在服务器中已经安装了 2.hiredis库 第二步安装hiredis 下载位置 2.1获取 安装包https://github.com/re ...
- Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
- poj3070 求斐波那契数列第n项 ——矩阵快速幂
题目:http://poj.org/problem?id=3070 用矩阵快速幂加速递推. 代码如下: #include<iostream> #include<cstdio> ...
- leetcode 395 至少有K个重复字符的最长子串
找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k .输出 T 的长度. 示例 1: 输入: s = "aaabb", k = 3 输 ...
- Lecture0 -- Introduction&&Linear Regression with One Variable
Introduction What is machine learning? Tom Mitchell provides a more modern definition: "A compu ...
- c++中编译链接总结
1 编译链接过程分为 预处理--->编译---->汇编---->链接.如下图所示 2 预处理都做了什么 (1)将所有的#define删除并展开所有的宏 (2)处理所有的条件预编译指令 ...