2018 China Collegiate Programming Contest Final (CCPC-Final 2018)(A B G I L)

A:签到题,正常模拟即可。

 1 #include
 2 using namespace std;
 3 const int maxn = 1e5 + 5;
 4 struct node{
 5     int id, time;
 6 };
 7 node a[maxn];
 8 bool cmp(const node &a, const node &b){
 9     if(a.id^b.id) return a.id < b.id;
10     else return a.time < b.time;
11 }
12 int main()
13 {
14     std::ios::sync_with_stdio(false);
15     int n, m, t;
16     cin >> t;
17     for(int cas = 1;cas <= t;cas++)
18     {
19         cin >> n >> m;
20         for(int i = 0;i < n;i++) cin >> a[i].id;
21         for(int i = 0;i < n;i++) cin >> a[i].time;
22         int ans = 0;sort(a, a + n, cmp);
23         int sum = 0;
24         for(int i = 0;i < n;i++)
25         {
26             if(sum + a[i].time <= m) sum += a[i].time, ans ++;
27             else break;
28         }
29         cout << "Case " << cas << ": ";
30         cout<< ans << endl;
31     }
32     return 0;
33 }
View Code

B:对于差值尽量小的问题,可以采用枚举最小值,然后使得最大值尽量小。

首先二分图判定,然后分块,求出每块的光明状态的最大最小值,黑暗状态的最大最小值,然后按分块编号塞到线段树离维护最大值,然后对这2*cnt个块由最小值从小到大进行排序,枚举每个块的最小值,然后更新答案,然后将这个块的最大值在线段树中删去,当某个块的光明状态和黑暗状态都被删去的时候,就不用继续枚举了。

  1 #include
  2 #define ls rt << 1
  3 #define rs rt << 1 | 1
  4 #define lr2 (l + r) >> 1
  5 #define lson l, mid, rt << 1
  6 #define rson mid + 1, r, rt << 1 | 1
  7 using namespace std;
  8 typedef long long ll;
  9 const int maxn = 5e5 + 50;
 10 const int INF = 0x3f3f3f3f;
 11 struct node{
 12     int maxx, minn, id;
 13     bool operator <(const node &b)const{
 14         return minn < b.minn;
 15     }
 16 };
 17 struct tree{
 18     pair<int, int> p[2];
 19     int val;
 20     void deleted(int x)
 21     {
 22         if(p[0].first == x) p[0].second = INF;
 23         else p[1].second = INF;
 24     }
 25 };
 26 int n, m, t;
 27 vector<int> G[maxn];
 28 int L[maxn], D[maxn];
 29 int color[maxn] , vis[maxn], cnt;
 30 tree T[maxn << 2];
 31 node A[maxn];
 32 bool flag;
 33 int num[maxn];
 34 void pushup(int rt)
 35 {
 36     T[rt].val = max(T[ls].val, T[rs].val);
 37 }
 38 void build(int l, int r, int rt)
 39 {
 40     if(l == r)
 41     {
 42         T[rt].p[0] = {A[l].minn, A[l].maxx};
 43         T[rt].p[1] = {A[l + cnt].minn, A[l + cnt].maxx};
 44         T[rt].val = min(A[l].maxx, A[l + cnt].maxx);
 45         return;
 46     }
 47     int mid = lr2;
 48     build(lson);
 49     build(rson);
 50     pushup(rt);
 51 }
 52 void update(int k, int v, int l, int r, int rt){
 53     if(l == r){
 54         T[rt].deleted(v);
 55         T[rt].val = min(T[rt].p[0].second, T[rt].p[1].second);
 56         return;
 57     }
 58     int mid = lr2;
 59     if(k <= mid) update(k, v, lson);
 60     else update(k, v ,rson);
 61     pushup(rt);
 62 }
 63 bool dfs(int v, int c, int id){
 64     color[v] = c;
 65     vis[v] = id;
 66     for(int i = 0;i < G[v].size();i++)
 67     {
 68         int u = G[v][i];
 69         if(color[u] == c) return false;
 70         if(!color[u]){
 71             if(!dfs(u, 3 - c, id)) return false;
 72         }
 73     }
 74     return true;
 75 }
 76 void init()
 77 {
 78     for(int i = 0;i <= n;i++) G[i].clear();
 79     fill(color, color + n + 100, 0);
 80     fill(vis, vis + n + 100, 0);
 81     fill(num, num + n + 100, 0);
 82     cnt = 0;flag = false;
 83 }
 84 int main()
 85 {
 86     std::ios::sync_with_stdio(false);
 87     cin >> t;
 88     for(int cas = 1; cas <= t;cas++)
 89     {
 90         cin >> n >> m;
 91         init();
 92         for(int i = 0;i < m;i++)
 93         {
 94             int a, b; cin >> a >> b;
 95             G[a].push_back(b);
 96             G[b].push_back(a);
 97         }
 98         for(int i = 1;i <= n;i++) cin >> L[i] >> D[i];
 99         for(int i = 1;i <= n;i++)
100         {
101             if(!vis[i])
102             {
103                 ++cnt;
104                 if(!dfs(i, 1, cnt))
105                 {
106                     flag = true;
107                     break;
108                 }
109             }
110         }
111         cout << "Case " << cas << ": ";
112         if(flag){
113             cout << "IMPOSSIBLE" << endl;
114             continue;
115         }
116         for(int i = 1;i <= 2 * cnt;i++)
117         {
118             A[i].maxx = 0, A[i].minn = INF;
119         }
120         for(int i = 1;i <= n;i++){
121             int x = vis[i];
122             if(color[i] == 1)
123             {
124                 A[x].id = x;
125                 A[x].maxx = max(A[x].maxx, L[i]);
126                 A[x].minn = min(A[x].minn, L[i]);
127                 A[x + cnt].id = x;
128                 A[x + cnt].maxx = max(A[x + cnt].maxx, D[i]);
129                 A[x + cnt].minn = min(A[x + cnt].minn, D[i]);
130             }
131             else{
132                 A[x].id = x;
133                 A[x].maxx = max(A[x].maxx, D[i]);
134                 A[x].minn = min(A[x].minn, D[i]);
135                 A[x + cnt].id = x;
136                 A[x + cnt].maxx = max(A[x + cnt].maxx, L[i]);
137                 A[x + cnt].minn = min(A[x + cnt].minn, L[i]);
138             }
139         }
140         build(1, cnt, 1);
141         sort(A + 1, A + 2 * cnt + 1);
142         int ans = INF;
143         for(int i = 1;i <= 2 * cnt;i++)
144         {
145             ans = min(ans, T[1].val - A[i].minn);
146             num[A[i].id]++;
147             if(num[A[i].id] == 2) break;
148             update(A[i].id, A[i].minn, 1, cnt, 1);
149         }
150         cout << ans << endl;
151     }
152     return 0;
153 }
View Code

G:题目大意:在一个n * m的土地,要在一个子矩形内放稻草人,稻草人必须被稻草包围,问合法的方法有多少种?

问题其实可以转化为:在n * m的草地上,选出一块子矩形,这个子矩形来放满稻草人必须被包括在n * m的矩形内。可以行和列分开考虑,(行的方案数) * (列的方案数)就是答案。一行可以选4个点,里面两个点是子矩形的宽的边界(列的边界),发现这样能确定一个子矩形的列的情况,但还有一种遗漏,就是只有一列的子矩形,这种情况只需要选三个点,所以是c[m][3] + c[m][4], 这样就确定了列的所有方案,行的方案跟列的方案类似。

 1 #include
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 1e5 + 5;
 5 const int mod = 1e9 + 7;
 6 ll C[maxn][5];
 7 void init()
 8 {
 9     C[0][0] = 1;
10     for(int i = 1; i <= maxn;i++)
11     {
12         C[i][0] = 1;
13         for(int j = 1; j <= 4;j++)
14             C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
15     }
16 }
17 int main()
18 {
19     std::ios::sync_with_stdio(false);
20     int n, m ,t;
21     cin >> t;
22     init();
23     for(int cas = 1;cas <= t;cas++)
24     {
25         cin >> n >> m;
26         ll h = (C[n][3] + C[n][4]) % mod;
27         ll w = (C[m][3] + C[m][4]) % mod;
28         ll ans = h * w % mod;
29         cout << "Case "<< cas << ": ";
30         cout << ans << endl;
31     }
32     return 0;
33 }
View Code

I:记录每个点的横纵坐标所在行列的点的数目,找到最大的maxx,maxy,max_x = maxx+maxy,其实消灭蟑螂的最大数目只能是max_x,或者max_x-1。

 1 #include
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 1e5 + 5;
 5 ll n;
 6 map<int,int> x, y;
 7 struct node{
 8     int x,y;
 9 };
10 node a[maxn];
11 int main()
12 {
13     std::ios::sync_with_stdio(false);
14     int t;
15     cin >> t;
16     for(int cas = 1; cas <=t; cas++){
17         cin >> n;
18         x.clear();
19         y.clear();
20         for(int i = 1; i <= n; i++){
21             cin >> a[i].x >> a[i].y;
22             x[a[i].x]++;
23             y[a[i].y]++;
24         }
25         int maxx = 0, maxy = 0;
26         for(int i = 1; i <= n; i++){
27             maxx = max(maxx, x[a[i].x]);
28             maxy = max(maxy, y[a[i].y]);
29         }
30         if(x.size() == 1 || y.size() == 1){
31             cout << "Case " << cas << ": " << n << " " << 1 << endl;
32         }
33         else{
34             if(maxx == 1 && maxy == 1){
35                 cout << "Case " << cas << ": " << 2 << " " << n*(n-1)/2 << endl;
36             }
37             else{
38                 ll x1 = 0, x2 = 0, y1 = 0, y2 = 0;
39                 map<int,int>::iterator it;
40                 for(it = x.begin(); it != x.end(); it++){
41                     if(it->second == maxx) x1++;
42                     else if(it->second == maxx - 1) x2++;
43                 }
44                 for(it = y.begin(); it != y.end(); it++){
45                     if(it->second == maxy) y1++;
46                     else if(it->second == maxy - 1) y2++;
47                 }
48                 ll ans1 = 0, ans2 = 0;
49                 ans1 = x1 * y1;
50                 ans2 = x2 * y1 + x1 * y2;
51                 for(int i = 1; i <= n; i++){
52                     if(maxx + maxy == x[a[i].x] + y[a[i].y]){
53                         ans1--;
54                         ans2++;
55                     }
56                     else if(maxx + maxy - 1 == x[a[i].x] + y[a[i].y]){
57                         ans2--;
58                     }
59                 }
60                 if(ans1){
61                     cout << "Case " << cas << ": " << maxx + maxy << " " << ans1 << endl;
62                 }
63                 else{
64                     cout << "Case " << cas << ": " << maxx + maxy - 1 << " " << ans2 << endl;
65                 }
66             }
67         }
68     }
69 
70 
71 }
View Code

L:贪心 + 分类讨论 + 暴力。小于等于11直接impossible, 然后奇数可以拆成 2 2 2 3 + 偶数, 偶数可以拆成2  2 2 2 + 偶数,对最后的偶数暴力分解即可。

 1 #include
 2 using namespace std;
 3 typedef long long ll;
 4 bool check(ll x)
 5 {
 6     int n = sqrt(x);
 7     for(int i = 2;i <= n;i++){
 8         if(x % i == 0)return false;
 9     }
10     return true;
11  
12 }
13 void print(ll n)
14 {
15     for(ll i = n - 2;i >= 2;i--){
16         if(check(i) && check(n - i)){
17             cout << " " << i << " " << n - i << endl;
18             return;
19         }
20     }
21 }
22 int main()
23 {
24     std::ios::sync_with_stdio(false);
25     int t;
26     cin >> t;
27     int cnt = 1;
28     while(t--)
29     {
30         ll n;
31         cin >> n;
32         cout << "Case "<< cnt++ <<": ";
33         if(n > 11)
34         {
35             if(n & 1)
36             {
37                 n -= 9LL;
38                 cout << "2 2 2 3";
39                 print(n);
40             }
41             else{
42                 n -= 8LL;
43                 cout << "2 2 2 2";
44                 print(n);
45             }
46         }
47         else cout << "IMPOSSIBLE" << endl;
48     }
49     return 0;
50 }
View Code

 

你可能感兴趣的:(2018 China Collegiate Programming Contest Final (CCPC-Final 2018)(A B G I L))