[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 ...
随机推荐
- Protocol_OSPF
Protocol_OSPF 作者:Danbo 2015-7-4 从一个非常概括的角度来看OSPF协议的操作是比较容易理解的 1.宣告OSPF的路由器从所有启动OSPF协议的接口上发出Hello数据包. ...
- ubuntu12.04不能记住上次编辑位置的解决方案
1:按照网上的代码 au BufReadPost * |if line("'\"") <= line("$")|exe("norm ' ...
- platform_set_drvdata()/platform_get_drvdata()/container_of()【转】
本文转载自:http://blog.csdn.net/angle_birds/article/details/8443695 platform_set_drvdata(struct platform_ ...
- chrome最小字体12px
http://www.mamicode.com/info-detail-512021.html http://www.divcss5.com/wenji/w738.shtml
- CISCO-更新路由器IOS
1,查看flash,复制IOS文件名,再上传IOS 2,传送完毕查看下flash Router# show flash: 查看flash中的信息 Directory of flash: 1 -rw- ...
- Linux GCC常用命令学习
1简介 GCC 的意思也只是 GNU C Compiler 而已.经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言:它现在还支持 Ada 语言.C++ 语言.Java 语言.Objective ...
- JavaScript DOM 编程艺术 ---> JavaScript语法
二. JavaScript语法目录 2.1 语法 javaScript代码要通过HTML/XHTML文档才能执行.可以有两种方式完成这一点,第一种是将JavaScript代码放到文档<head ...
- 什么是weex
Weex是一个使用web开发体验来开发高性能原生应用的框架 在集成WeexSDK之后,你可以使用javaScript和现代流行的前端框架来开发移动应用. Weex的结构是解耦的,渲染引擎与语法层是分开 ...
- JS正则对象 RegExp(有变量的时候使用),用来匹配搜索关键字(标红)
1,平常我们写js正则规则的时候,一般是这样写: var reg = /abc/; 然而,这样写的话,如果abc是一个变量这样就不行,我们需要下面这种写法: var abc = "汉字&qu ...
- StackOverFlow页面不正常,因为CDN被墙了
190.93.247.58 cdn.sstatic.net 198.252.206.140 sstatic.net http://stackoverflow.com/