UOJ#77. A+B Problem

题目名称是吸引你点进来的。

从前有个 n 个方格排成一行,从左至右依此编号为 1,2,,n

有一天思考熊想给这 n 个方格染上黑白两色。

第 i 个方格上有 6 个属性:ai,bi,wi,li,ri,pi

如果方格 i 染成黑色就会获得 bi 的好看度。

如果方格 i 染成白色就会获得 wi 的好看度。

但是太多了黑色就不好看了。如果方格 i 是黑色,并且存在一个 j 使得 1j<i 且 liajri 且方格 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

保证 liri

输出格式

一个非负整数表示所有染色方案中最大的好看度。

样例一

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+w10p67+4+4+9+5+6+6+5+3+7155

 

限制与约定

设 amax 为 a,l,r 中的最大值,vmax 为 b,w 中的最大值, pmax 为 p 中的最大值。

测试点编号namaxvmaxpmax
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;
}
View Code

正解:

#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;
}
View Code

 

posted @ 2015-07-16 18:36  wzj_is_a_juruo  阅读(556)  评论(0编辑  收藏  举报