从这里开始
- 题目目录
- 在题解前面的话
- Problem A Tetris
- Problem B Lecture Sleep
- Problem C Chessboard
- Problem D Pair Of Lines
- Problem E Tufurama
- Problem F k-substrings
- Problem G Partitions
在题解前面的话
只是AFO前再来玩一玩cf。由于第二天模拟赛,晚上没有去参加这场比赛。由于省选的缘故,Practise的时候只有时间AC掉了前5道题目。以后可能会填坑。
Problem A Tetris
题目大意
有一个$n$列的空间,第$i$次放置方块,将它放在第$a_{i}$列上。当一行被填满时可以得到1点分数,问最终的分数。
按题目要求做。最后取最小值。
Code
1 /** 2 * Codeforces 3 * Problem#961A 4 * Accepted 5 * Time: 31ms 6 * Memory: 3400k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 int n, m; 13 int *cnt; 14 15 inline void init() { 16 scanf("%d%d", &n, &m); 17 cnt = new int[(n + 1)]; 18 memset(cnt, 0, sizeof(int) * (n + 1)); 19 for (int i = 1, x; i <= m; i++) { 20 scanf("%d", &x); 21 cnt[x]++; 22 } 23 } 24 25 int minv = 211985; 26 inline void solve() { 27 for (int i = 1; i <= n; i++) 28 minv = min(minv, cnt[i]); 29 printf("%d\n", minv); 30 } 31 32 int main() { 33 init(); 34 solve(); 35 return 0; 36 }
Problem B Lecture Sleep
题目大意
有一个人听课,在$i$分钟,老师讲了$a_{i}$个定理,这个人的状态为$t_{i}$。如果$t_{i} = 0$那么这个人在打瞌睡不会记下任何定理,如果$t_{i} = 1$那么这个人会在这个时刻记下所有老师讲的定理。现在你可让他在连续$k$分钟的$t$都变1,问他能够记下的最大的定理数目。
根据题目意思做。
Code
1 /** 2 * Codeforces 3 * Problem#961B 4 * Accepted 5 * Time: 46ms 6 * Memory: 4200k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 int n, k; 13 int *ar, *tr; 14 int res = 0, maxv = 0; 15 16 inline void init() { 17 scanf("%d%d", &n, &k); 18 ar = new int[(n + 1)]; 19 tr = new int[(n + 1)]; 20 for (int i = 1; i <= n; i++) 21 scanf("%d", ar + i); 22 for (int i = 1; i <= n; i++) 23 scanf("%d", tr + i), res += tr[i] * ar[i]; 24 } 25 26 int sum = 0; 27 inline void solve() { 28 for (int i = 1; i <= n; i++) { 29 if (i > k) sum -= ar[i - k] * (1 - tr[i - k]); 30 sum += ar[i] * (1 - tr[i]); 31 maxv = max(maxv, sum); 32 } 33 printf("%d", res + maxv); 34 } 35 36 int main() { 37 init(); 38 solve(); 39 return 0; 40 }
Problem C Chessboard
题目大意
有4个$n \times n$的棋盘,将它拼成$2n \times 2n$的棋盘(不能旋转或者翻着)。你可以对它进行重现染色,要求相邻两格的格子颜色不同,问最少的重新染色的次数。
根据题目意思暴力。
Code
1 /** 2 * Codeforces 3 * Problem#961C 4 * Accepted 5 * Time: 31ms 6 * Memory: 3500k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 const int N = 105; 13 14 int n; 15 char ar[4][N][N]; 16 char buf[N << 1][N << 1]; 17 18 inline void init() { 19 scanf("%d", &n); 20 for (int k = 0; k <= 3; k++) { 21 for (int i = 0; i < n; i++) 22 scanf("%s", ar[k][i]); 23 } 24 } 25 26 void copyMat(char arr[][N], int hei, int wid, int x, int y) { 27 for (int i = x; i < x + hei; i++) 28 for (int j = y; j < y + wid; j++) 29 buf[i][j] = arr[i - x][j - y]; 30 } 31 32 int res = 211985; 33 void calc() { 34 int rt = 0; 35 for (int i = 0; i < (n << 1); i++) 36 for (int j = 0; j < (n << 1); j++) 37 if (((i + j) & 1) + ‘0‘ != buf[i][j]) 38 rt++; 39 res = min(res, rt); 40 res = min(res, n * n * 4 - rt); 41 } 42 43 boolean vis[4]; 44 void dfs(int x, int y) { 45 if (x == 2) { 46 calc(); 47 return; 48 } 49 for (int i = 0; i < 4; i++) { 50 if (!vis[i]) { 51 vis[i] = true; 52 copyMat(ar[i], n, n, n * x, n * y); 53 if (y == 1) 54 dfs(x + 1, 0); 55 else 56 dfs(x, y + 1); 57 vis[i] = false; 58 } 59 } 60 } 61 62 inline void solve() { 63 dfs(0, 0); 64 printf("%d\n", res); 65 } 66 67 int main() { 68 init(); 69 solve(); 70 return 0; 71 }
Problem D Pair Of Lines
题目大意
二维平面上有$n$个不相同的点,问是否存在两条的直线,使得每个点存在于任意一条直线上。
如果存在答案的话,那么我任意取三个点,它们其中两个会在答案中的一条直线上。
那么我枚举这两个点,然后判断是否可行。
Code
1 /** 2 * Codeforces 3 * Problem#961D 4 * Accepted 5 * Time: 108ms 6 * Memory: 5000k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 const double eps = 1e-8; 13 14 int dcmp(double x) { 15 if (fabs(x) < eps) return 0; 16 return (x < 0) ? (-1) : (1); 17 } 18 19 typedef class Point { 20 public: 21 double x, y; 22 23 Point(double x = 0.0, double y = 0.0):x(x), y(y) { } 24 }Vector, Point; 25 26 Vector operator - (Point a, Point b) { 27 return Point(a.x - b.x, a.y - b.y); 28 } 29 30 double cross(Vector a, Vector b) { 31 return a.x * b.y - a.y * b.x; 32 } 33 34 int n; 35 Point *ps; 36 37 inline void init() { 38 scanf("%d", &n); 39 ps = new Point[(n + 1)]; 40 for (int i = 1; i <= n; i++) 41 scanf("%lf%lf", &ps[i].x, &ps[i].y); 42 } 43 44 boolean check(int ia, int ib) { 45 Vector AB = ps[ib] - ps[ia]; 46 Point p[2]; 47 int top = 0; 48 for (int i = 1; i <= n; i++) { 49 if (i == ia || i == ib) 50 continue; 51 if (!dcmp(cross(ps[i] - ps[ib], AB))) 52 continue; 53 if (top < 2) 54 p[top++] = ps[i]; 55 else { 56 if (dcmp(cross(ps[i] - p[1], p[1] - p[0]))) 57 return false; 58 } 59 } 60 return true; 61 } 62 63 inline void solve() { 64 if (n <= 3) 65 puts("YES"); 66 else { 67 if (check(1, 2) || check(1, 3) || check(2, 3)) 68 puts("YES"); 69 else 70 puts("NO"); 71 } 72 } 73 74 int main() { 75 init(); 76 solve(); 77 return 0; 78 }
Problem E Tufurama
题目大意
给定一个数组$a$。问存在多少个数对$(x, y)$,满足$x < y, a_{x} \geqslant y$且$a_{y} \geqslant x$。
考虑从小到大枚举$y$。那么对于一个$a_{x}$如果它不满足条件$a_{x} \geqslant y$,那么它永远都不会再满足了。
于是可以用堆来维护$a_{i}$,用树状数组维护有贡献的地方。
Code
1 /** 2 * Codeforces 3 * Problem#961E 4 * Accepted 5 * Time: 93ms 6 * Memory: 8100k 7 */ 8 #include <bits/stdc++.h> 9 #ifdef WIN32 10 #define Auto "%I64d" 11 #else 12 #define Auto "%lld" 13 #endif 14 using namespace std; 15 typedef bool boolean; 16 17 typedef class IndexedTree { 18 public: 19 int s; 20 int *ar; 21 22 IndexedTree() { } 23 IndexedTree(int n):s(n) { 24 ar = new int[(n + 1)]; 25 memset(ar, 0, sizeof(int) * (n + 1)); 26 } 27 28 void add(int idx, int val) { 29 for ( ; idx <= s; idx += (idx & (-idx))) 30 ar[idx] += val; 31 } 32 33 int getSum(int idx) { 34 int rt = 0; 35 for ( ; idx; idx -= (idx & (-idx))) 36 rt += ar[idx]; 37 return rt; 38 } 39 }IndexedTree; 40 41 #define pii pair<int, int> 42 #define ll long long 43 44 int n; 45 int *ar; 46 IndexedTree it; 47 priority_queue<pii> que; 48 49 inline void init() { 50 scanf("%d", &n); 51 it = IndexedTree(n); 52 ar = new int[(n + 1)]; 53 for (int i = 1; i <= n; i++) 54 scanf("%d", ar + i); 55 } 56 57 ll res = 0; 58 inline void solve() { 59 it.add(1, 1); 60 que.push(pii(-ar[1], 1)); 61 for (int i = 2; i <= n; i++) { 62 while (!que.empty() && que.top().first > -i) { 63 int e = que.top().second; 64 que.pop(); 65 it.add(e, -1); 66 } 67 res += it.getSum(min(ar[i], i - 1)); 68 it.add(i, 1); 69 que.push(pii(-ar[i], i)); 70 } 71 printf(Auto, res); 72 } 73 74 int main() { 75 init(); 76 solve(); 77 return 0; 78 }