2020.10.2 19级training 补题报告

B - Yet Another Crosses Problem

 1.题意

  有一个n行m列的矩阵,每个格子都被涂上了黑色或白色,如果某一格的所在行和列都是黑色,就形成了一个十字架,问至少把几个白格子涂成黑色才能至少有一个十字架。

 2.题解

  分别用两个数组存每一行和每一列的黑格数,遍历矩阵,维护把所在行和列都变成黑色的最小改变格数。

 3.代码

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 int t;
 5 int main() {
 6     cin >> t;
 7     while(t--) {
 8         int n, m;
 9         cin >> n >> m;
10         int a[50005] = {0}; //存行的*数量 
11         int b[50005] = {0}; //存列的*数量  
12         
13         char p[n+5][m+5];
14         for(int i = 0; i < n; i++) {
15             getchar();
16             for(int j = 0; j < m; j++) {
17                 scanf("%c", &p[i][j]);
18                 if(p[i][j] == '*') {
19                     a[i]++;
20                     b[j]++;
21                 }
22             }
23         }
24         
25         int ans = 1e18; 
26         for(int i = 0; i < n; i++) {
27             for(int j = 0; j < m; j++) {
28                 int  num = n + m - a[i] - b[j];
29                 if(p[i][j] == '.') {
30                     num--;    
31                 }
32                 if(ans > num) {
33                     ans = num;
34                 }
35                 if(ans == 0) {
36                     break;    
37                 }
38             }
39             if(ans == 0) {
40                 break;    
41             }
42         }
43         cout << ans << endl;
44     }
45     
46     return 0;
47 }
View Code

D - Glider

 1.题意

  飞机在h米的高空水平飞行,飞行员可以在任意整数点跳伞,跳伞过程中,每秒飞行员都会向前移动一米,向下移动一米。有n个不相交的区间,飞行员在这些区间上空飞行时不会下降,给出每个区间的左右端点,求飞行员从跳伞到降落的最大水平距离。

 2.题解

  明显应该从某个气流左端跳伞,气流的宽度对高度没影响,所以我们要考虑气流之间的距离,因为要找一段连续的长度,所以气流长度与气流之间的距离都应该用前缀和,用二分查找飞行员的落地点,再处理一下边界情况就好了。

 3.代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct seg {
 4     int x1;
 5     int x2;
 6 }s[200005];
 7 int n, h, m[200005];
 8 vector<int> d;
 9 int main(){
10     scanf("%d%d%d%d", &n, &h, &s[0].x1, &s[0].x2);
11     m[0] = 0;
12     d.push_back(0);
13     for(int i = 1; i < n; i++) {
14         scanf("%d%d", &s[i].x1, &s[i].x2);
15         d.push_back(s[i].x1 - s[i-1].x2 + d[i-1]);
16         m[i] = s[i-1].x2 - s[i-1].x1 + m[i-1];
17     }
18     m[n] = s[n-1].x2 - s[n-1].x1 + m[n-1];
19     int ans = 0;
20     for(int l = 0; l < n; l++) {
21         int r = upper_bound(d.begin(), d.end(), h + d[l]) - d.begin() - 1;
22         if(d[r] - d[l] < h) {
23             ans = max(ans, h + m[r+1] - m[l]);
24         }
25         if(d[r] - d[l] == h) {
26             ans = max(ans, max(s[r].x1 - s[l].x1, s[r].x2 - s[l].x2)); 
27         }
28     }
29     cout << ans << endl;
30     
31     return 0;
32 }
View Code

F - Coffee Break

 1.题意

  小明想要在工作的n个时刻休息一分钟,两次休息的间隔不得小于d分钟,每天的工作时间为m分钟。问最少用几天休息完,并输出在哪一天实行了哪次休息。

 2.题解

  用set把休息时刻都存进去,选取最小的放进第一天,二分查找是否还有能放进第一天的休息时刻,没有就放到下一天,依次查找。

 3.代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 2e5 + 5;
 4 struct node {
 5     int v, id;
 6     bool operator < (const node d)const {
 7         return v < d.v;
 8     }
 9 }x;
10 int n, m, d;
11 int pos[maxn];
12 set<node> a;
13 set<node>::iterator it;
14 int main() {
15     scanf("%d%d%d", &n, &m, &d);
16     for(int i = 1; i <= n; i++) {
17         scanf("%d", &x.v);
18         x.id=i;
19         a.insert(x);
20     }
21     
22     int now = (*a.begin()).v;
23     int cnt = 1;
24     pos[(*a.begin()).id] = 1;
25     a.erase(a.begin());
26     for(int i = 2; i<= n; i++) {
27         node x;
28         x.v = now + d + 1;
29         it = a.lower_bound(x);
30         if(it != a.end()) {
31             pos[(*it).id] = cnt;
32             now = (*it).v;
33             a.erase(it);
34             continue;
35         }
36         cnt++;
37         it = a.begin();
38         pos[(*it).id] = cnt;
39         now = (*it).v;
40         a.erase(it);
41     }
42     printf("%d
", cnt);
43     for(int i = 1; i <= n; ++i) {
44         printf("%d ", pos[i]);
45     }
46     
47     return 0;
48 }
View Code
原文地址:https://www.cnblogs.com/lvguapi/p/13763736.html