codeforces 628F

来源:互联网 发布:淘宝代销店加盟 编辑:程序博客网 时间:2024/05/09 13:55

原题

原题链接

题目大意

给你一个集合的大小N,N5的倍数。
然后有一些限制:
集合里的数范围是[1,b].
集合中的数mod5=0,1,2,3,4的数的个数各为N/5
还有q个附加限制,就是元素值为[1,upToi]的个数为quantityi
问是否存在一个集合满足条件。

范围

(5nb104,1q104)

解题思路

我们不妨加一个限制就是元素值为[1,b]的个数为n。这样,我们的限制就可以描述集合了。先按限制的upTo排序,对于限制i以及限制i1,在upToi1upToi之间增加的数的个数就是quantityiquantityi1,而且在这个区间中,增加的数对5取模的个数也是可以算出来的。

然后就可以使用网络流了,(S,mod0,n/5),(S,mod1,n/5),(S,mod2,n/5),(S,mod3,n/5),(S,mod4,n/5),表示mod不同值的个数都是n/5,(i,T,quantityiquantityi1),还有就是把每个区间的对5取模的个数求出来连边就行了。

参考程序

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)#define maxn 10055#define cannot() puts("unfair")#define can() puts("fair")#define oo 1e9using namespace std;int n,b,q,S,T;int head[maxn],t[maxn*20],next[maxn*20],v[maxn*20],sum;int tmp[10];struct note{    int up,num;}a[maxn];bool cmp(note i,note j){    return i.up<j.up||i.up==j.up && i.num<j.num;}void ins(int x,int y,int z){    t[++sum]=y;    v[sum]=z;    next[sum]=head[x];    head[x]=sum;}void insert(int x,int y,int z){    ins(x,y,z);    ins(y,x,0);}int vh[maxn],dis[maxn],di[maxn],his[maxn],pre[maxn],ans;void sap(){    int tp=T;    bool p;    vh[0]=tp+1;    int x=S;    int aug=oo;    while (dis[S]<tp){        p=0;        his[x]=aug;        for(int i=di[x];i;i=next[i]){            if (v[i]&&dis[t[i]]+1==dis[x]){                p=1;                di[x]=i;                pre[t[i]]=x;                aug=min(aug,v[i]);                x=t[i];                if (x==T){                    ans+=aug;                    while (x!=S){                        int tmp=x;                        x=pre[x];                        v[di[x]]-=aug;                        v[di[x] ^ 1]+=aug;                    }                    aug=oo;                }                break;            }        }        if (!p){            int k,min;            min=tp+1;            for(int i=head[x];i;i=next[i]){                if (v[i]&&min>dis[t[i]]){                    min=dis[t[i]];                    k=i;                }            }            --vh[dis[x]];            if (vh[dis[x]]==0) break;            vh[++min]++;            dis[x]=min;            di[x]=k;            if (x!=S){                x=pre[x];                aug=his[x];            }        }    }}int main(){    sum=1;    scanf("%d%d%d",&n,&b,&q);    fo(i,1,q) scanf("%d%d",&a[i].up,&a[i].num);    a[++q].up=b;    a[q].num=n;    sort(a+1,a+q+1,cmp);    fo(i,2,q){        if (a[i].up==a[i-1].up&&a[i].num!=a[i-1].num){            cannot();            return 0;        }        if (a[i].up>a[i-1].up&&a[i].num<a[i-1].num){            cannot();            return 0;        }    }    S=0;    T=q+1;    fo(i,1,q){        if (i>1) tmp[0]=a[i].num-a[i-1].num;        else tmp[0]=a[i].num;        int down;        if (i>1) down=a[i-1].up;        else down=0;        insert(S,i,tmp[0]);        fo(j,0,4) tmp[j]=a[i].up / 5;        fo(j,0,a[i].up % 5) tmp[j]++;        fo(j,0,4) tmp[j]-=down/5;        fo(j,0,down % 5) tmp[j]--;        fo(j,0,4) insert(i,T+j,tmp[j]);    }    fo(i,0,4) insert(T+i,T+5,n / 5);    T+=5;    sap();    if (ans==n) can();    else cannot();    return 0;}
0 0
原创粉丝点击