BZOJ 4937: [Ceoi2016]popeala

题解链接:http://pan.baidu.com/s/1dFHAlIL 密码:ug38

#include
#define cp(a,x) memcpy(a,x,sizeof a)
using namespace std;
const int N=20002,inf=(1ll<<31)-1;
inline int read(){
    int x=0,f=1; char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return x*f;
}
int n,m,q,a[N],p0[52];
char s[52][N];
int f[N],t[N],g[N];
struct Q{
    int q[N],l,r,d;
    void pre(){l=1,r=0;}
    void add(int x){
        if(f[x]==inf)return;
        int u=f[x]-a[x]*d;
        while(l<=r){
            int y=q[r];
            if(f[y]-a[y]*d>=u)--r; else break;
        }
        q[++r]=x;
    }
    void del(int x){
        if(l<=r && q[l]==x)++l;
    }
    int get(int w){
        if(l>r)return inf;
        int x=q[l];
        return f[x]+(a[w]-a[x])*d;
    }
}qs[52];
int main(){
    n=read(),m=read(),q=read();
    for(int i=1;i<=m;++i) a[i]=read()+a[i-1];
    for(int i=1;i<=n;++i){
        scanf("%s",s[i]+1); qs[i].d=i;
        for(int j=1;j<=m && s[i][j]=='1';++j) f[j]+=a[j];
    }
    printf("%d\n",f[m]);
    for(int i=2;i<=q;++i){
        for(int j=0;j<=n;++j) p0[j]=0,qs[j].pre();
        f[0]=inf;
        for(int j=1;j<=m;++j){
            qs[t[j]=n].add(j-1);
            for(int k=1;k<=n;++k) if(s[k][j]=='0'){
                for(int z=p0[k]+1;z<=j;++z){
                    qs[t[z]].del(z-1);
                    qs[--t[z]].add(z-1);
                }
                p0[k]=j;
            }
            g[j]=inf;
            for(int k=0;k<=n;++k) g[j]=min(g[j],qs[k].get(j));
        }
        cp(f,g);
        printf("%d\n",f[m]);
    }
    return 0;
}

你可能感兴趣的:(bzoj,DP,单调队列)