UOJ#77. A+B Problem
题目名称是吸引你点进来的。
从前有个 n 个方格排成一行,从左至右依此编号为 1,2,⋯,n。
有一天思考熊想给这 n 个方格染上黑白两色。
第 i 个方格上有 6 个属性:ai,bi,wi,li,ri,pi。
如果方格 i 染成黑色就会获得 bi 的好看度。
如果方格 i 染成白色就会获得 wi 的好看度。
但是太多了黑色就不好看了。如果方格 i 是黑色,并且存在一个 j 使得 1≤j<i 且 li≤aj≤ri 且方格 j 为白色,那么方格 i 就被称为奇怪的方格。
如果方格 i 是奇怪的方格,就会使总好看度减少 pi。
也就是说对于一个染色方案,好看度为:
现在给你 n,a,b,w,l,r,p,问所有染色方案中最大的好看度是多少。
输入格式
第一行一个正整数 n。
接下来 n 行中第 i 行有用空格隔开的 6 个非负整数依次表示 ai,bi,wi,li,ri,pi。
保证 li≤ri。
输出格式
一个非负整数表示所有染色方案中最大的好看度。
样例一
input
10
0 1 7 3 9 2
7 4 0 9 10 5
1 0 4 2 10 2
7 9 1 5 7 2
6 3 5 3 6 2
6 6 4 1 8 1
6 1 6 0 6 5
2 2 5 0 9 3
5 1 3 0 2 5
5 6 7 1 1 2
output
55
explanation
最优染色方案为:白 黑 白 黑 白 黑 白 白 白 白
可以发现只有方格 6 为奇怪的方格。
所以好看度为:
限制与约定
设 amax 为 a,l,r 中的最大值,vmax 为 b,w 中的最大值, pmax 为 p 中的最大值。
| 测试点编号 | n | amax | vmax | pmax |
|---|---|---|---|---|
| 1 | =5 | ≤10 | ≤10 | ≤10 |
| 2 | =20 | ≤40 | ≤40 | ≤40 |
| 3 | =20 | ≤40 | ≤40 | ≤40 |
| 4 | =5000 | ≤10 | ≤200000 | ≤100000 |
| 5 | =5000 | ≤10 | ≤200000 | ≤300000 |
| 6 | =200 | ≤109 | ≤200000 | ≤200000 |
| 7 | =300 | ≤109 | ≤200000 | ≤220000 |
| 8 | =500 | ≤109 | ≤200000 | ≤400000 |
| 9 | =5000 | ≤5000 | ≤200000 | ≤150000 |
| 10 | =5000 | ≤109 | ≤200000 | ≤300000 |
时间限制:2s
空间限制:48MB
来源
VFleaKing
看WZJ这蒟蒻卡爆测评机2333333
都在这里了http://oj.cnuschool.org.cn/oj/home/educationArchiveList.htm A+B,登陆后下载
由于我现推的,和VFK论文中的写的正好相反。
暴力:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<queue>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
const int maxn=;
const int maxm=;
struct Dinic {
int n,m,s,t,nowd;
int vis[maxn],d[maxn],cur[maxn],first[maxn],next[maxm];
struct Edge {int from,to,flow;}edges[maxm];
void init(int n) {
this->n=n;m=;
fill(first+,first+n+,-);
}
void AddEdge(int u,int v,int w) {
edges[m]=(Edge){u,v,w};next[m]=first[u];first[u]=m++;
edges[m]=(Edge){v,u,};next[m]=first[v];first[v]=m++;
}
int BFS() {
queue<int> Q;
Q.push(s);d[s]=;vis[s]=++nowd;
while(!Q.empty()) {
int x=Q.front();Q.pop();cur[x]=first[x];
ren {
Edge& e=edges[i];
if(e.flow&&vis[e.to]!=nowd) {
vis[e.to]=nowd;
d[e.to]=d[x]+;
Q.push(e.to);
}
}
}
return vis[t]==nowd;
}
int DFS(int x,int a) {
if(x==t||!a) return a;
int flow=,f;
for(int& i=cur[x];i!=-;i=next[i]) {
Edge& e=edges[i];
if(d[e.to]==d[x]+&&(f=DFS(e.to,min(e.flow,a)))) {
flow+=f;a-=f;
e.flow-=f;edges[i^].flow+=f;
if(!a) break;
}
}
return flow;
}
int solve(int s,int t) {
this->s=s;this->t=t;
int flow=;
while(BFS()) flow+=DFS(s,1e9);
return flow;
}
}sol;
int n,a[maxn],b[maxn],w[maxn],l[maxn],r[maxn],p[maxn];
void solve() {
int S=*n+,T=*n+,all=;sol.init(T);
rep(,n) sol.AddEdge(S,i,w[i]),sol.AddEdge(i,T,b[i]),all+=w[i]+b[i];
rep(,n) {
for(int j=;j<i;j++) if(l[i]<=a[j]&&a[j]<=r[i]) sol.AddEdge(j,i+n,1e9);
sol.AddEdge(i+n,i,p[i]);
}
printf("%d\n",all-sol.solve(S,T));
}
int main() {
n=read();
rep(,n) a[i]=read(),b[i]=read(),w[i]=read(),l[i]=read(),r[i]=read(),p[i]=read();
solve();
return ;
}
正解:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<queue>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
const int maxn=;
const int maxm=;
struct Dinic {
int n,m,s,t,nowd;
int vis[maxn],d[maxn],cur[maxn],first[maxn],next[maxm];
struct Edge {int from,to,flow;}edges[maxm];
void init() {
m=;
memset(first,-,sizeof(first));
}
void AddEdge(int u,int v,int w) {
if(!u||!v) return;
edges[m]=(Edge){u,v,w};next[m]=first[u];first[u]=m++;
edges[m]=(Edge){v,u,};next[m]=first[v];first[v]=m++;
}
int BFS() {
queue<int> Q;
Q.push(s);d[s]=;vis[s]=++nowd;
while(!Q.empty()) {
int x=Q.front();Q.pop();cur[x]=first[x];
ren {
Edge& e=edges[i];
if(e.flow&&vis[e.to]!=nowd) {
vis[e.to]=nowd;
d[e.to]=d[x]+;
Q.push(e.to);
}
}
}
return vis[t]==nowd;
}
int DFS(int x,int a) {
if(x==t||!a) return a;
int flow=,f;
for(int& i=cur[x];i!=-;i=next[i]) {
Edge& e=edges[i];
if(d[e.to]==d[x]+&&(f=DFS(e.to,min(e.flow,a)))) {
flow+=f;a-=f;
e.flow-=f;edges[i^].flow+=f;
if(!a) break;
}
}
return flow;
}
int solve(int s,int t) {
this->s=s;this->t=t;
int flow=;
while(BFS()) flow+=DFS(s,1e9);
return flow;
}
}sol;
int n,a[],b[],w[],l[],r[],p[];
int root[maxn],ls[maxn],rs[maxn],ToT;
void build(int& y,int x,int l,int r,int pos,int v) {
y=++ToT;
if(l==r) {
if(x) sol.AddEdge(x,y,1e9);
sol.AddEdge(v,y,1e9);
return;
}
int mid=l+r>>;ls[y]=ls[x];rs[y]=rs[x];
if(pos<=mid) build(ls[y],ls[x],l,mid,pos,v);
else build(rs[y],rs[x],mid+,r,pos,v);
if(ls[y]) sol.AddEdge(ls[y],y,1e9);
if(rs[y]) sol.AddEdge(rs[y],y,1e9);
}
void query(int y,int l,int r,int ql,int qr,int v) {
if(!y) return;
if(ql<=l&&r<=qr) {sol.AddEdge(y,v,1e9);return;}
int mid=l+r>>;
if(ql<=mid) query(ls[y],l,mid,ql,qr,v);
if(qr>mid) query(rs[y],mid+,r,ql,qr,v);
}
int tmp[],cnt;
void pre() {
int m=;
rep(,n) tmp[++m]=a[i],tmp[++m]=l[i],tmp[++m]=r[i];
sort(tmp+,tmp+m+);cnt=m;
rep(,n) a[i]=lower_bound(tmp+,tmp+m+,a[i])-tmp;
rep(,n) l[i]=lower_bound(tmp+,tmp+m+,l[i])-tmp;
rep(,n) r[i]=lower_bound(tmp+,tmp+m+,r[i])-tmp;
}
void solve() {
int S=*n+,T=*n+,all=;sol.init();ToT=T;
rep(,n) sol.AddEdge(S,i,w[i]),sol.AddEdge(i,T,b[i]),all+=w[i]+b[i];
rep(,n) {
query(root[i],,cnt,l[i],r[i],i+n);
sol.AddEdge(i+n,i,p[i]);build(root[i+],root[i],,cnt,a[i],i);
}
printf("%d\n",all-sol.solve(S,T));
}
int main() {
n=read();
rep(,n) a[i]=read(),b[i]=read(),w[i]=read(),l[i]=read(),r[i]=read(),p[i]=read();
pre();solve();
return ;
}
UOJ#77. A+B Problem的更多相关文章
- UOJ#77. A+B Problem [可持久化线段树优化建边 最小割]
UOJ#77. A+B Problem 题意:自己看 接触过线段树优化建图后思路不难想,细节要处理好 乱建图无果后想到最小割 白色和黑色只能选一个,割掉一个就行了 之前选白色必须额外割掉一个p[i], ...
- BZOJ 3218 UOJ #77 A+B Problem (主席树、最小割)
大名鼎鼎的A+B Problem, 主席树优化最小割-- 调题死活调不对,一怒之下改了一种写法交上去A了,但是改写法之后第4,5个点常数变大很多,于是喜提UOJ全站倒数第三 目前还不知道原来的写法为什 ...
- BZOJ3218 UOJ#77 A+B Problem(最小割+主席树)
竟然在BZOJ上拿了Rank1太给力啦. p.s.:汗,一发这个就被一堆人在2月27号强势打脸-- 传送门(BZOJ) 传送门(UOJ) 说说这道题目吧: 首先是说说这个构图吧.因为有选择关系,我们很 ...
- 【BZOJ3218】【UOJ#77】a + b Problem
题目 题目在这里 思路&做法 明显的最小割(其实是之前做过一道类似的题) S向每一个格子连容量为\(b_i\)的边 每一个格子向T连容量为\(w_i\)的边 对于格子\(i\)向满足条件的格子 ...
- 【UOJ#77】A+B Problem
传送门 题目描述 略 Sol 看到选择黑白收益不同,然后还可能有代价. 我们想到用网络流解决,并且这应该是用总可能收益-最小割得到答案. 考虑初步建图,发现那个限制可以直接 \(n^2\) 解决. 我 ...
- UOJ#XX A+B Problem (罔烙硫)
题面 背景 题目描述 从前有个 n n n 个方格排成一行,从左至右依此编号为 1 , 2 , ⋯ , n 1,2,⋯,n 1,2,⋯,n. 有一天思考熊想给这 n n n 个方格染上黑白两色. 第 ...
- 【UOJ #246】【UER #7】套路
http://uoj.ac/contest/35/problem/246 神奇!我这辈子是想不出这样的算法了. 对区间长度分类讨论:题解很好的~ 我已经弱到爆了,看完题解后还想了一晚上. 题解中&qu ...
- 【UOJ #244】【UER #7】短路
http://uoj.ac/contest/35/problem/244 对其他人来说好简单的一道题,我当时却不会做TWT 注定滚粗啊 题解很好的~ #include<cstdio> #i ...
- UOJ 180【UR #12】实验室外的攻防战
http://uoj.ac/contest/25/problem/180 从前往后对比串A,B 当$A_i,B_i$不相同时找到$B_i$在A中的位置j 若$min{A_1,A_2,A_3...... ...
随机推荐
- Linux生产服务器Shell脚本分享
Linux生产服务器Shell脚本分享 2012-6-6 86市场网 linux 作为一名Linux/unix系统管理员,我经常遇到人问这个问题:shell能做什么?PHP这么强大,为什么不用PHP来 ...
- linux 下如何查看和踢除正在登陆的其它用户 ==>Linux下用于查看系统当前登录用户信息的4种方法
在linux系统中用pkill命令踢出在线登录用户 由于linux服务器允许多用户登录,公司很多人知道密码,工作造成一定的障碍 所以需要有时踢出指定的用户 1/#who 查出当前有那些终端登录(用 ...
- digitalocean添加ssh_keys
链接为: https://cloud.digitalocean.com/settings/security
- PHP 调试用函数
2014年7月4日 10:27:59 有些系统函数可以在调试程序时救急用: get_class_methods(); get_class_vars(); get_object_vars(); get_ ...
- 用php实现遍历目录
用php实现的遍历目录,只遍历第一层,如果制作在线文件管理器的话很管用,不同目录只加一个超链接就行了,然后给方法传递参数就行了,遍历目录的类如下: class Ergodic{ public func ...
- MST:Conscription(POJ 3723)
男女搭配,干活不累 题目大意:需要招募女兵和男兵,每一个人都的需要花费1W元的招募费用,但是如果有一些人之间有亲密的关系,那么就会减少一定的价钱,如果给出1~9999的人之间的亲密关系,现在要你求 ...
- Cocos2d-JS游戏导演
什么是游戏的导演 具体来说,Cocos2d-JS中的导演是一个对象,它负责设置游戏的运行环境,控制游戏的住循环并且管理场景和场景的切换. 导演的任务 Cocos2d-JS中导演对象名为:cc.dire ...
- CodeForces - 424B (贪心算法)
Megacity Time Limit: 2000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u Submit Sta ...
- Linux C 知识 char型数字转换为int型 int型 转换为Char
前言 在九度oj做acm的时候,经常会遇到了char类型和int类型相互转化的问题,这里进行一下总结.今后,可能会多次更新博客,因为半年做了很多总结,但是都是保存在word文档上了,现在开始慢慢向CS ...
- STL —— STL六大组件
注:以下内容摘自 http://blog.csdn.net/byxdaz/article/details/4633826 STL六大组件 容器(Container) 算法(Algorithm) 迭代器 ...