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 }
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 }
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 }