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。
也就是说对于一个染色方案,好看度为:
∑方格i为黑色bi+∑方格i为白色wi−∑方格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 为奇怪的方格。
所以好看度为:
==w1+b2+w3+b4+w5+b6+w7+w8+w9+w10−p67+4+4+9+5+6+6+5+3+7−155
限制与约定
设 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=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=100010; const int maxm=200010; 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=0; fill(first+1,first+n+1,-1); } 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,0};next[m]=first[v];first[v]=m++; } int BFS() { queue<int> Q; Q.push(s);d[s]=0;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]+1; Q.push(e.to); } } } return vis[t]==nowd; } int DFS(int x,int a) { if(x==t||!a) return a; int flow=0,f; for(int& i=cur[x];i!=-1;i=next[i]) { Edge& e=edges[i]; if(d[e.to]==d[x]+1&&(f=DFS(e.to,min(e.flow,a)))) { flow+=f;a-=f; e.flow-=f;edges[i^1].flow+=f; if(!a) break; } } return flow; } int solve(int s,int t) { this->s=s;this->t=t; int flow=0; 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=2*n+1,T=2*n+2,all=0;sol.init(T); rep(1,n) sol.AddEdge(S,i,w[i]),sol.AddEdge(i,T,b[i]),all+=w[i]+b[i]; rep(1,n) { for(int j=1;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(1,n) a[i]=read(),b[i]=read(),w[i]=read(),l[i]=read(),r[i]=read(),p[i]=read(); solve(); return 0; }
正解:
#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=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=100010; const int maxm=400010; 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=0; memset(first,-1,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,0};next[m]=first[v];first[v]=m++; } int BFS() { queue<int> Q; Q.push(s);d[s]=0;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]+1; Q.push(e.to); } } } return vis[t]==nowd; } int DFS(int x,int a) { if(x==t||!a) return a; int flow=0,f; for(int& i=cur[x];i!=-1;i=next[i]) { Edge& e=edges[i]; if(d[e.to]==d[x]+1&&(f=DFS(e.to,min(e.flow,a)))) { flow+=f;a-=f; e.flow-=f;edges[i^1].flow+=f; if(!a) break; } } return flow; } int solve(int s,int t) { this->s=s;this->t=t; int flow=0; while(BFS()) flow+=DFS(s,1e9); return flow; } }sol; int n,a[5010],b[5010],w[5010],l[5010],r[5010],p[5010]; 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>>1;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+1,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>>1; if(ql<=mid) query(ls[y],l,mid,ql,qr,v); if(qr>mid) query(rs[y],mid+1,r,ql,qr,v); } int tmp[15010],cnt; void pre() { int m=0; rep(1,n) tmp[++m]=a[i],tmp[++m]=l[i],tmp[++m]=r[i]; sort(tmp+1,tmp+m+1);cnt=m; rep(1,n) a[i]=lower_bound(tmp+1,tmp+m+1,a[i])-tmp; rep(1,n) l[i]=lower_bound(tmp+1,tmp+m+1,l[i])-tmp; rep(1,n) r[i]=lower_bound(tmp+1,tmp+m+1,r[i])-tmp; } void solve() { int S=2*n+1,T=2*n+2,all=0;sol.init();ToT=T; rep(1,n) sol.AddEdge(S,i,w[i]),sol.AddEdge(i,T,b[i]),all+=w[i]+b[i]; rep(1,n) { query(root[i],1,cnt,l[i],r[i],i+n); sol.AddEdge(i+n,i,p[i]);build(root[i+1],root[i],1,cnt,a[i],i); } printf("%d\n",all-sol.solve(S,T)); } int main() { n=read(); rep(1,n) a[i]=read(),b[i]=read(),w[i]=read(),l[i]=read(),r[i]=read(),p[i]=read(); pre();solve(); return 0; }