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

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

 1 #include<bits/stdc++.h>
 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 }

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

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

  1 #include<bits/stdc++.h>
  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 }

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

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

 1 #include<bits/stdc++.h>
 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 }

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

 1 #include<bits/stdc++.h>
 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 }

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

 1 #include<bits/stdc++.h>
 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 }

原文地址:https://www.cnblogs.com/Carered/p/11622883.html

时间: 2024-09-30 11:49:40

2018 China Collegiate Programming Contest Final (CCPC-Final 2018)(A B G I L)的相关文章

模拟赛小结:2018 China Collegiate Programming Contest Final (CCPC-Final 2018)

比赛链接:传送门 跌跌撞撞6题摸银. 封榜后两题,把手上的题做完了还算舒服.就是罚时有点高. 开出了一道奇奇怪怪的题(K),然后ccpcf银应该比区域赛银要难吧,反正很开心qwq. Problem A. Mischievous Problem Setter 00:14 (-2) Solved by Dancepted 良心签到题.WA2吃乳猪. 代码: #include <iostream> #include <cmath> #include <map> #includ

2018 German Collegiate Programming Contest (GCPC 18)

2018 German Collegiate Programming Contest (GCPC 18) Attack on Alpha-Zet 建树,求lca 代码: #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bit

(寒假GYM开黑)2018 German Collegiate Programming Contest (GCPC 18)

layout: post title: 2018 German Collegiate Programming Contest (GCPC 18) author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队博客 C.Coolest Ski Route (记忆化搜索) 题意 给出一个有向图,求出一个权值最长的链, 题解 暴力dfs会超时,所以直接储存每个起点能走到的最远距离 #include<

The 2019 China Collegiate Programming Contest Harbin Site F. Fixing Banners

链接: https://codeforces.com/gym/102394/problem/F 题意: Harbin, whose name was originally a Manchu word meaning "a place for drying fishing nets", grew from a small rural settlement on the Songhua River to become one of the largest cities in Northea

2019 China Collegiate Programming Contest Qinhuangdao Onsite

目录 Contest Info Solutions A. Angle Beats D. Decimal F. Forest Program I. Invoker J. MUV LUV EXTRA Contest Info Practice Link Solved A B C D E F G H I J K L 5/12 O - - O - O - - - O ? - O 在比赛中通过 ? 赛后通过 ! 尝试了但是失败了 - 没有尝试 Solutions A. Angle Beats 题意: 给出

The 2019 China Collegiate Programming Contest Harbin Site

目录 Contest Info Solutions A. Artful Paintings E. Exchanging Gifts F. Fixing Banners I. Interesting Permutation J. Justifying the Conjecture K. Keeping Rabbits L. LRU Algorithm Contest Info Practice Link Solved A B C D E F G H I J K L 6/12 O - - - O O

2018 Arab Collegiate Programming Contest (ACPC 2018) G. Greatest Chicken Dish (线段树+GCD)

题目链接:https://codeforces.com/gym/101991/problem/G 题意:给出 n 个数,q 次询问区间[ li,ri ]之间有多少个 GCD = di 的连续子区间. 题解:类似HDU 5726,可以先看一下这个blog:https://blog.csdn.net/u013569304/article/details/51987053 考虑离线,先预处理出[ 1,n ]之间所有的GCD,同时需要记录每种 GCD 的区间,方法是固定一个右端点R,对于区间[ L,R

The 2019 China Collegiate Programming Contest Harbin Site K. Keeping Rabbits

链接: https://codeforces.com/gym/102394/problem/K 题意: DreamGrid is the keeper of n rabbits. Initially, the i-th (1≤i≤n) rabbit has a weight of wi. Every morning, DreamGrid gives the rabbits a carrot of weight 1 and the rabbits fight for the only carrot

The 2019 China Collegiate Programming Contest Harbin Site J. Justifying the Conjecture

链接: https://codeforces.com/gym/102394/problem/J 题意: The great mathematician DreamGrid proposes a conjecture, which states that: Every positive integer can be expressed as the sum of a prime number and a composite number. DreamGrid can't justify his c