您的位置:首页 > 其它

codeforces 628F

2016-03-19 12:07 239 查看

原题

原题链接

题目大意

给你一个集合的大小NN,NN是55的倍数。

然后有一些限制:

集合里的数范围是[1,b][1,b].

集合中的数mod5=0,1,2,3,4mod 5=0,1,2,3,4的数的个数各为N/5N/5。

还有qq个附加限制,就是元素值为[1,upToi][1,upTo_i]的个数为quantityiquantity_i。

问是否存在一个集合满足条件。

范围

(5 ≤ n ≤ b ≤ 104,1 ≤ q ≤ 104)(5 ≤ n ≤ b ≤ 10^4, 1 ≤ q ≤ 10^4)

解题思路

我们不妨加一个限制就是元素值为[1,b][1,b]的个数为nn。这样,我们的限制就可以描述集合了。先按限制的upToupTo排序,对于限制ii以及限制i−1i-1,在upToi−1upTo_{i-1}到upToiupTo_i之间增加的数的个数就是quantityi−quantityi−1quantity_i-quantity_{i-1},而且在这个区间中,增加的数对5取模的个数也是可以算出来的。

然后就可以使用网络流了,(S,mod0,n/5)(S,mod0,n / 5),(S,mod1,n/5)(S,mod1,n / 5),(S,mod2,n/5)(S,mod2,n / 5),(S,mod3,n/5)(S,mod3,n / 5),(S,mod4,n/5)(S,mod4,n / 5),表示modmod不同值的个数都是n/5n / 5,(i,T,quantityi−quantityi−1)(i,T,quantity_i-quantity_{i-1}),还有就是把每个区间的对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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: