题意:
给定N,B,Q≤104,N能被5整除
N为set大小(无相同元素),元素范围为[1,B],需满足set里元素模5的余数为[0,4]的元素个数相等
Q个条件,bi cnti,表示[1,bi]应该有cnti个数
问这种set是否存在,存在输出“fair”,否则“unfair”
分析:
把题目条件(B,N)和Q次询问一起按照Bi排序,这样形成了Q+1个不相交区间(加上一个(0,0))
建图,源点→Remainders0∼4,容量为n/5;区间→汇点,容量为cnti
Remaindersi→区间,容量为区间里数模5余Remainderi的个数
考虑求Remainders的匹配数,存在性即可以最大流判断是不是N
网络流求解,666
代码:
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 3100
#define MOD 1000000007
const int MAXN = 100010;
const int MAXM = 400010;
struct Edge
{
int to,next,cap,flow;
} edge[MAXM];
int tot,n,m,q;
int head[MAXN];
int gap[MAXN],dep[MAXN];
int pre[MAXN],cur[MAXN];
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void add_edge(int u,int v,int w,int rw = 0)
{
edge[tot].to = v;
edge[tot].cap = w;
edge[tot].flow = 0;
edge[tot].next = head[u];
head[u] = tot++;
edge[tot].to = u;
edge[tot].cap = rw;
edge[tot].flow = 0;
edge[tot].next = head[v];
head[v] = tot++;
}
int sap(int start,int en,int N)
{
memset(gap,0,sizeof(gap));
memset(dep,0,sizeof(dep));
memcpy(cur,head,sizeof(head));
int u = start;
pre[u] = -1;
gap[0] = N;
int ans = 0;
while(dep[start] < N)
{
if(u == en)
{
int Min = INF;
for(int i = pre[u]; i != -1; i = pre[edge[i^1].to])
if(Min > edge[i].cap - edge[i].flow)
Min = edge[i].cap - edge[i].flow;
for(int i = pre[u]; i != -1; i = pre[edge[i^1].to])
{
edge[i].flow += Min;
edge[i^1].flow -= Min;
}
u = start;
ans += Min;
continue;
}
int flag = 0;
int v;
for(int i = cur[u]; i != -1; i = edge[i].next)
{
v = edge[i].to;
if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u])
{
flag = 1;
cur[u] = pre[v] = i;
break;
}
}
if(flag)
{
u = v;
continue;
}
int Min = N;
for(int i = head[u]; i != -1; i = edge[i].next)
if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
{
Min = dep[edge[i].to];
cur[u] = i;
}
gap[dep[u]]--;
if(!gap[dep[u]])
return ans;
dep[u] = Min + 1;
gap[dep[u]]++;
if(u != start)
u = edge[pre[u]^1].to;
}
return ans;
}
struct node
{
int x,y;
bool operator<(const node&a)const
{
return x < a.x;
}
}a[10010];
int solve(int x,int y,int k)
{
int k1 = x % 5;
int k2 = y % 5;
x += 5 - k1;
y -= k2 + 1;
return (y - x + 1) / 5 + (k1 <= k) + (k2 >= k);
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t,C = 1;
//scanf("%d",&t);
while(scanf("%d%d%d",&n,&m,&q) != EOF)
{
init();
int flag = 1;
for(int i = 1; i <= q; i++)
scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+q+1);
a[0].x = 0;
a[0].y = 0;
for(int i = 1; i <= q; i++)
{
int k = a[i].y-a[i-1].y;
add_edge(0,i,k);
if(k < 0 || k > a[i].x - a[i-1].x)
flag = 0;
for(int j = 1; j <= 5; j++)
add_edge(i,q+1+j,solve(a[i-1].x+1,a[i].x,j-1));
}
if(a[q].x != m)
{
int k = n-a[q].y;
add_edge(0,q+1,k);
if(k < 0 || k > m - a[q].x)
flag = 0;
for(int j = 1; j <= 5; j++)
add_edge(q+1,q+1+j,solve(a[q].x+1,m,j-1));
}
for(int i = 1; i <= 5; i++)
add_edge(q+1+i,q+7,n/5);
if(flag && sap(0,q+7,q+8) == n)
printf("fair\n");
else
printf("unfair\n");
}
return 0;
}