题解

最小割+主席树优化建图

首先看到每个点只有\(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的更多相关文章

  1. 1199 Problem B: 大小关系

    求有限集传递闭包的 Floyd Warshall 算法(矩阵实现) 其实就三重循环.zzuoj 1199 题 链接 http://acm.zzu.edu.cn:8000/problem.php?id= ...

  2. 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 ...

  3. C - NP-Hard Problem(二分图判定-染色法)

    C - NP-Hard Problem Crawling in process... Crawling failed Time Limit:2000MS     Memory Limit:262144 ...

  4. Time Consume Problem

    I joined the NodeJS online Course three weeks ago, but now I'm late about 2 weeks. I pay the codesch ...

  5. Programming Contest Problem Types

        Programming Contest Problem Types Hal Burch conducted an analysis over spring break of 1999 and ...

  6. hdu1032 Train Problem II (卡特兰数)

    题意: 给你一个数n,表示有n辆火车,编号从1到n,入站,问你有多少种出站的可能.    (题于文末) 知识点: ps:百度百科的卡特兰数讲的不错,注意看其参考的博客. 卡特兰数(Catalan):前 ...

  7. BZOJ2301: [HAOI2011]Problem b[莫比乌斯反演 容斥原理]【学习笔记】

    2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 4032  Solved: 1817[Submit] ...

  8. [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 ...

  9. [LeetCode] The Skyline Problem 天际线问题

    A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...

随机推荐

  1. 原来 Set 集合也可以排序

    Java 集合类主要由两个接口派生而出: Collection 和 Map.在 Collection 集合中,我们经常用到的是 List 集合和 Map 集合,而 Set 集合出场的机会就相对比较的少 ...

  2. Android应用资源---动画资源(Animation Resources)

    有两种类型的动画资源: 属性动画 在设定的时间内,通过修改与Animator类相关的对象的属性值来创建一个动画. 视图动画 有两种类型的视图动画框架 补间动画(Tween animation):通过执 ...

  3. linux应用之基本命令

    linux操作系统的应用层可以细分为两层:1.系统服务层(包括GUI shell.CUI shell.cron.ftp.远程登录openssh等由init调用的服务)2.系统命令和用户应用. linu ...

  4. python berkeley 操作——尤其提示 需版本匹配

    python berkeley 操作 先到http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/dow ...

  5. 不能访问tomcat中的项目

    tomcat在eclipse里面能正常启动,而在浏览器中访问http://localhost:8080/不能访问,且报404错误.同时其他项目页面也不能访问. 关闭eclipse里面的tomcat,在 ...

  6. vuex 命名空间

    默认情况下,模块内部的action mutation getter是注册在全局命名空间的,如果希望你的模块具有更高的封装度和复用性,你可以通过添加namespaced:true的方式使其成为带命名空间 ...

  7. saltstack master minion安装配置简单使用

    首先先了解下saltstack是什么,为什么使用它 它与Ansible.Puppet都属于集中管理工具,由于现在企业规模的不断庞大及业务的增长,所需要管理的服务器数量增多,而且大部分机器都属于同类业务 ...

  8. py-day17-jquery

    jquery实现案例 案例: 1.点赞 <!DOCTYPE html> <html lang="en"> <head> <meta cha ...

  9. HDOJ-2048

    神.上帝以及老天爷 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total S ...

  10. Eigen::aligned_allocator

    http://blog.csdn.net/rs_huangzs/article/details/50574141