topcoder ArrayTransformations

来源:互联网 发布:淘宝美工助理广州 编辑:程序博客网 时间:2024/05/29 00:32

首先考虑模型,从s0..n1连边,从1..nt连边,从ii+1连费用为1的边,再对s限流,这样每条增广路就对应选择了一段区间。
接下来考虑具体要求,可以二分答案然后对边加上下界。

#include<cstring>#include<vector>#include<string>#include<sstream>#include<algorithm>using namespace std;const int maxn=310,p=300,maxm=400010,s=285,s1=286,t=287,S=288,T=289,oo=0x3f3f3f3f;class ArrayTransformations{    int fir[maxn],ne[maxm],to[maxm],w[maxm],c[maxm],    que[maxn],dep[maxn],dis[maxn],mnw[maxn],pre[maxn],inq[maxn],    a[maxn],n,k,m,num;private:    void prt()    {        for (int i=0;i<=T;i++)            for (int j=fir[i];j;j=ne[j])                if (w[j])                    printf("%d->%d:%d,%d\n",i,to[j],w[j],c[j]);    }    void inc(int &x)    {        x=x+1==p?0:x+1;    }    void add(int u,int v,int x,int y)    {        num++;        ne[num*2]=fir[u];        fir[u]=num*2;        to[num*2]=v;        w[num*2]=x;        c[num*2]=y;        ne[num*2+1]=fir[v];        fir[v]=num*2+1;        to[num*2+1]=u;        w[num*2+1]=0;        c[num*2+1]=-y;    }    int find(int &x)    {        int hd=0,tl=1,u,v;        memset(mnw,0,sizeof(mnw));        mnw[S]=oo;        memset(dis,0x3f,sizeof(dis));        dis[S]=0;        que[0]=S;        inq[S]=1;        while (hd!=tl)        {            u=que[hd];            inc(hd);            for (int i=fir[u];i;i=ne[i])                if (w[i]&&dis[u]+c[i]<dis[v=to[i]])                {                    dis[v]=dis[u]+c[i];                    mnw[v]=min(mnw[u],w[i]);                    pre[v]=i;                    if (!inq[v])                    {                        que[tl]=v;                        inc(tl);                        inq[v]=1;                    }                }            inq[u]=0;        }        if (!mnw[T]) return 0;        for (int i=pre[T];i;i=pre[to[i^1]])        {            w[i]-=mnw[T];            w[i^1]+=mnw[T];        }        x=mnw[T]*dis[T];        return 1;    }    int check(int x)    {        int ans=0;        memset(fir,0,sizeof(fir));        num=0;        add(s,s1,k,0);        add(t,s,oo,0);        for (int i=0;i<n;i++) add(s1,i,oo,0);        for (int i=1;i<=n;i++) add(i,t,oo,0);        for (int i=1;i<=n;i++)        {            add(i-1,i,oo,1);            if (a[i]>x)            {                add(i-1,T,a[i]-x,0);                add(S,i,a[i]-x,0);                ans+=a[i]-x;            }        }        //if (x==5||x==6) prt();        while (find(x)) ans+=x;        return ans<=m;    }public:    int minimalValue(vector<string> initialArray,int K,int M)    {        stringstream st;        int x,l,r,mid;        k=K;        m=M;        for (vector<string>::iterator it=initialArray.begin();it!=initialArray.end();++it)        {            st.clear();            st.str(*it);            while (st>>x) a[++n]=x;        }        r=0;        for (int i=1;i<=n;++i) r=max(r,a[i]);        l=max(0,r-k);        while (l<r)        {            mid=(l+r)/2;            if (check(mid)) r=mid;            else l=mid+1;        }        return l;    }};
0 0
原创粉丝点击