codeforces 628F

原題

原題鏈接

題目大意

給你一個集合的大小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 1e9
using 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章