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

Posted carered

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 
View Code

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 
View Code

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 
View Code

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 
View Code

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 
View Code

 

以上是关于2018 China Collegiate Programming Contest Final (CCPC-Final 2018)(A B G I L)的主要内容,如果未能解决你的问题,请参考以下文章

Fight Against Monsters (2018-2019 ACM-ICPC, China Multi-Provincial Collegiate Programming Contest)(T

2018 China Collegiate Programming Contest - Guilin Site(D/H/G/J/A)

2018 China Collegiate Programming Contest - Guilin Site(D/H/G/J/A)

2018 China Collegiate Programming Contest - Guilin Site(D/H/G/J/A)

Rolling The Polygon (2018-2019 ACM-ICPC, China Multi-Provincial Collegiate Programming Contest)(The

2018-2019 ACM-ICPC, China Multi-Provincial Collegiate G. Factories(树形dp+算贡献)