# Codeforces CF#628 Education 8 F. Bear and Fair Set

F. Bear and Fair Set
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Limak is a grizzly bear. He is big and dreadful. You were chilling in the forest when you suddenly met him. It's very unfortunate for you. He will eat all your cookies unless you can demonstrate your mathematical skills. To test you, Limak is going to give you a puzzle to solve.

It's a well-known fact that Limak, as every bear, owns a set of numbers. You know some information about the set:

• The elements of the set are distinct positive integers.
• The number of elements in the set is n. The number n is divisible by 5.
• All elements are between 1 and b, inclusive: bears don't know numbers greater than b.
• For each r in {0, 1, 2, 3, 4}, the set contains exactly elements that give remainder r when divided by 5. (That is, there are elements divisible by 5, elements of the form 5k + 1, elements of the form 5k + 2, and so on.)

Limak smiles mysteriously and gives you q hints about his set. The i-th hint is the following sentence: "If you only look at elements that are between 1 and upToi, inclusive, you will find exactly quantityi such elements in my set."

In a moment Limak will tell you the actual puzzle, but something doesn't seem right... That smile was very strange. You start to think about a possible reason. Maybe Limak cheated you? Or is he a fair grizzly bear?

Given nbq and hints, check whether Limak can be fair, i.e. there exists at least one set satisfying the given conditions. If it's possible then print ''fair". Otherwise, print ''unfair".

Input

The first line contains three integers nb and q (5 ≤ n ≤ b ≤ 104, 1 ≤ q ≤ 104, n divisible by 5) — the size of the set, the upper limit for numbers in the set and the number of hints.

The next q lines describe the hints. The i-th of them contains two integers upToi and quantityi (1 ≤ upToi ≤ b0 ≤ quantityi ≤ n).

Output

Print ''fair" if there exists at least one set that has all the required properties and matches all the given hints. Otherwise, print ''unfair".

Examples
input
10 20 110 10
output
fair
input
10 20 315 105 010 5
output
fair
input
10 20 215 320 10
output
unfair
Note

In the first example there is only one set satisfying all conditions: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}.

In the second example also there is only one set satisfying all conditions: {6, 7, 8, 9, 10, 11, 12, 13, 14, 15}.

Easy to see that there is no set satisfying all conditions from the third example. So Limak lied to you :-(

题意：
有n个不同的数字，每个数字都在1-b之间。
按照每个数对5取余进行分类，每一类的数都有n/5个。
现在给出q个条件。
1-up_i之间，包含那n个数的个数。
求，这些条件有没有可能全为真。


题解：
这道题目很精妙。
是一道简单的线性规划和网络流问题。
首先根据q个条件我们可以得到若干个区间，
知道这些区间各自包含n个数字的哪几个数。
首先对于每个区间，
我们可以设x0,x1,x2..x4为每个类里面的数的数目。
然后这么多个区间，我们得到了xi,0、xi,1、...、xi,4，
并且我们有sigma(xi_0)=n/5，
并且每个数非零。

那如果我们这样建图，
由源向li连边，流量为n/5，
由汇向ri连边，流量为各个区间包含的数目。
每个li代表第i类点的总数，ri代表区间的数目总和。
那么每个li向每个ri连边，流量代表ri这个区间最多包含几个li这个类的点。
如果有可行流（满流），代表有一种分配方案符合条件。  1 #include <cstdio>
2 #include <cstring>
3 #include <cstdlib>
4 #include <ctime>
5 #include <string>
6 #include <cmath>
7 #include <iostream>
8 #include <algorithm>
9 #include <queue>
10 #include <vector>
11 #include <map>
12 #include <set>
13 #include <deque>
14 using namespace std;
15 typedef long long ll;
16 const int INF = 1000000001, MIT = (1ll << 31) - 1;
17 const ll MLL = 1e18 + 1;
18 #define sz(x) ((int) (x).size())
19
20 class ISap {
21     /**
22      * Time Complexity: O(N^2*M)
23      * Special Case Time Complexity:
24      *        If the capacity and flow are integer, the time complexity is
25      *        O(min{N^(2/3), M^(1/2)}*M)
26      * Improve:
27      *        Gap, Multiple Augmented, Manual Stack, Active Label
28      * Usage:
29      *        init()
31      *        [preLabel()]
32      *        maxflow()
33      *    preLabel function is not nessary. But will slower 10% if not use.
34      * */
35 private :
36     static const int N = 10020, M = 60510, INF = 1000000001;
37 public :
38     int fir[N], nex[M * 2], son[M * 2], cap[M * 2], flow[M * 2], totEdge;
39     int gap[N], dep[N], src, des, totPoint;
40
41     void init(int _totPoint) {
42         totEdge = 0, totPoint = _totPoint;
43         for(int i = 0; i <= totPoint; ++i)
44             gap[i] = dep[i] = 0, fir[i] = -1;
45     }
46
47     void addEdge(const int u, const int v, const int c) {
48         nex[totEdge] = fir[u], son[totEdge] = v, cap[totEdge] = c, flow[totEdge] = 0;
49         fir[u] = totEdge++;
50         nex[totEdge] = fir[v], son[totEdge] = u, cap[totEdge] = c, flow[totEdge] = c;
51         fir[v] = totEdge++;
52     }
53
54     void preLabel() {
55         static int que[N], head, tail;
56         head = tail = 0;
57         for(int i = 0; i <= totPoint; ++i) dep[i] = totPoint, gap[i] = 0;
58
59         que[tail++] = des, dep[des] = 0, ++gap;
62             for(int tab = fir[u], v; tab != -1; tab = nex[tab]) {
63                 if(flow[tab ^ 1] >= cap[tab ^ 1]) continue;
64                 if(dep[v = son[tab]] < totPoint) continue;
65                 ++gap[dep[v] = dep[u] + 1], que[tail++] = v;
66             }
67         }
68     }
69
70     int maxflow() {
71         static int cur[N], rev[N];
72         int flows = 0;
73         for(int i = 0; i <= totPoint; ++i) cur[i] = fir[i];
74         for(int u = src; dep[u] < totPoint && dep[src] < totPoint; ) {
75             if(u == des) {
76                 int nowFlow = INF;
77                 for(int p = src; p != des; p = son[cur[p]])
78                     nowFlow = min(nowFlow, cap[cur[p]] - flow[cur[p]]);
79                 for(int p = src; p != des; p = son[cur[p]])
80                     flow[cur[p]] += nowFlow, flow[cur[p] ^ 1] -= nowFlow;
81                 flows += nowFlow, u = src;
82             }
83
84             int tab;
85             for(tab = cur[u]; tab != -1; tab = nex[tab])
86                 if(cap[tab] > flow[tab] && dep[u] == dep[son[tab]] + 1) break;
87             if(tab != -1) {
88                 cur[u] = tab, rev[son[tab]] = tab ^ 1;
89                 u = son[tab];
90             } else {
91                 if(--gap[dep[u]] == 0) break;
92                 cur[u] = fir[u];
93                 int minDep = totPoint;
94                 for(tab = fir[u]; tab != -1; tab = nex[tab])
95                     if(cap[tab] > flow[tab]) minDep = min(minDep, dep[son[tab]]);
96                 ++gap[dep[u] = minDep + 1];
97                 if(u != src) u = son[rev[u]];
98             }
99         }
100         return flows;
101     }
102 };
103 int n, b, q;
104 vector<pair<int, int> > hints;
105
106 int calculate(int lef, int rig, int r) {
107     if(!r) r = 5;
108     --lef;
109     rig = rig / 5 + (rig % 5 >= r);
110     lef = lef < 0 ? 0 : lef / 5 + (lef % 5 >= r);
111     return rig - lef;
112 }
113
114 void solve() {
115     hints.push_back(make_pair(b, n)), ++q;
116     sort(hints.begin(), hints.end());
117
118     ISap *maxflow = new ISap();
119     maxflow->init(5 + q + 2);
120     maxflow->src = 5 + q + 1, maxflow->des = 5 + q + 2;
121     int st = 0, lastQuan = 0;
122     for(int remainder = 0; remainder < 5; ++remainder)
123         maxflow->addEdge(maxflow->src, remainder + 1, n / 5);
124     for(int i = 0; i < q; ++i) {
125         int nowQuan = hints[i].second - lastQuan;
126         if(nowQuan < 0) {
127             puts("unfair");
128             return;
129         }
130         maxflow->addEdge(5 + i + 1, maxflow->des, nowQuan);
131
132         int ed = hints[i].first;
133         for(int remainder = 0; remainder < 5; ++remainder) {
134             int cnt = calculate(st, ed, remainder);
135             maxflow->addEdge(remainder + 1, 5 + i + 1, cnt);
136         }
137         st = ed + 1, lastQuan = hints[i].second;
138     }
139
140     int ans = maxflow->maxflow();
141
142     puts(ans == n ? "fair" : "unfair");
143 }
144
145 int main() {
146     scanf("%d%d%d", &n, &b, &q);
147     for(int i = 0; i < q; ++i) {
148         int upto, quan;
149         scanf("%d%d", &upto, &quan);
150         hints.push_back(make_pair(upto, quan));
151     }
152     solve();
153     return 0;
154 }
View Code

posted @ 2016-12-02 14:43  yanzx6  阅读(251)  评论(0编辑  收藏