agc033
A题意:给你个黑白矩阵,每次黑的周围一圈会变黑,求多少次之后全黑。n <= 1000
解:BFS即可。
1 #include <bits/stdc++.h> 2 3 const int N = 1010; 4 const int dx[] = {1, 0, -1, 0}; 5 const int dy[] = {0, 1, 0, -1}; 6 7 struct Node { 8 int x, y; 9 Node(int X = 0, int Y = 0) { 10 x = X; 11 y = Y; 12 } 13 }; 14 15 int vis[N][N], d[N][N]; 16 char str[N]; 17 std::queue<Node> Q; 18 19 int main() { 20 21 int n, m, ans = 0; 22 scanf("%d%d", &n, &m); 23 for(int i = 1; i <= n; i++) { 24 scanf("%s", str + 1); 25 for(int j = 1; j <= m; j++) { 26 if(str[j] == '#') { 27 Q.push(Node(i, j)); 28 vis[i][j] = 1; 29 d[i][j] = 0; 30 } 31 } 32 } 33 34 while(Q.size()) { 35 int x = Q.front().x, y = Q.front().y; 36 Q.pop(); 37 for(int i = 0; i < 4; i++) { 38 int tx = x + dx[i], ty = y + dy[i]; 39 if(tx < 1 || ty < 1 || tx > n || ty > m || vis[tx][ty]) { 40 continue; 41 } 42 vis[tx][ty] = 1; 43 d[tx][ty] = d[x][y] + 1; 44 Q.push(Node(tx, ty)); 45 ans = std::max(ans, d[tx][ty]); 46 } 47 } 48 printf("%d\n", ans); 49 return 0; 50 }
B题意:给你个矩阵,初始时有个棋子在(sx,sy)。先后手都有个字符串,每一回合可以选择不走或者按照字符串上的方向走一步。先手想要玩完n回合,后手想要在n回合之内把棋子走出棋盘。谁能如愿以偿呢?n <= 20w
解:发现行列独立。于是考虑行。我们从后往前,维护第i步时棋子在哪些地方会导致在n步内出棋盘。判断一下是否必出棋盘即可。列同理。
1 #include <bits/stdc++.h> 2 3 const int N = 200010; 4 5 char str1[N], str2[N]; 6 int n; 7 8 int main() { 9 10 int n1, n2, x1, x2; 11 scanf("%d%d%d", &n1, &n2, &n); 12 scanf("%d%d", &x1, &x2); 13 scanf("%s%s", str1 + 1, str2 + 1); 14 15 bool f = 1; 16 int L = 0, R = n1 + 1; 17 for(int i = n; i >= 1; i--) { 18 19 if(str2[i] == 'L' || str2[i] == 'R') { 20 21 } 22 else if(str2[i] == 'D') { 23 L = std::max(L - 1, 0); 24 } 25 else { 26 R = std::min(R + 1, n1 + 1); 27 } 28 29 if(str1[i] == 'L' || str1[i] == 'R') { 30 31 } 32 else if(str1[i] == 'D') { 33 R = R - 1; 34 } 35 else { 36 L = L + 1; 37 } 38 if(L + 1 >= R) { 39 f = 0; 40 break; 41 } 42 43 } 44 if(x1 <= L || R <= x1) { 45 f = 0; 46 } 47 L = 0, R = n2 + 1; 48 for(int i = n; i >= 1 && f; i--) { 49 50 if(str2[i] == 'U' || str2[i] == 'D') { 51 52 } 53 else if(str2[i] == 'L') { 54 R = std::min(R + 1, n2 + 1); 55 } 56 else { 57 L = std::max(L - 1, 0); 58 } 59 60 if(str1[i] == 'U' || str1[i] == 'D') { 61 62 } 63 else if(str1[i] == 'L') { 64 L = L + 1; 65 } 66 else { 67 R = R - 1; 68 } 69 if(L + 1 >= R) { 70 f = 0; 71 break; 72 } 73 74 } 75 if(x2 <= L || R <= x2) { 76 f = 0; 77 } 78 if(f) { 79 printf("YES\n"); 80 } 81 else { 82 printf("NO\n"); 83 } 84 return 0; 85 }
C题意:给你一棵树,每个点上有一个硬币。两个人轮流选择一个有硬币的点,把该点的硬币取走并把其它点的硬币都向这个点挪一步。不能操作者输。问谁输?n <= 20w
解:发现与每个点的具体硬币数量没关系,只跟是否有硬币有关系。然后发现每一次就是删掉所有叶子,但是你可以选择保护一个叶子不被删。我们感性想象一下,发现跟每某个点的伸出去的最长链有关系...
然后考虑直径,别问我怎么想到的...灵光一闪就想到了。发现每次操作之后,直径要么减2要么减1,就算直径改变了,但是长度仍然遵守这个规律。且最后剩下来的是一条单个的直径。于是求出直径长度,sg函数即可。(其实有个规律......)
1 #include <bits/stdc++.h> 2 3 const int N = 200010; 4 5 struct Edge { 6 int nex, v; 7 }edge[N << 1]; int tp; 8 9 int n, e[N], sg[N], f[N], Ans; 10 11 inline void add(int x, int y) { 12 edge[++tp].v = y; 13 edge[tp].nex = e[x]; 14 e[x] = tp; 15 return; 16 } 17 18 void DFS(int x, int fa) { 19 int a = 1, b = 0; 20 for(int i = e[x]; i; i = edge[i].nex) { 21 int y = edge[i].v; 22 if(y == fa) continue; 23 DFS(y, x); 24 if(a < f[y] + 1) { 25 b = a; 26 a = f[y] + 1; 27 } 28 else { 29 b = std::max(b, f[y] + 1); 30 } 31 } 32 Ans = std::max(Ans, std::max(a + b - 1, a)); 33 f[x] = a; 34 return; 35 } 36 37 int main() { 38 39 int n; 40 scanf("%d", &n); 41 for(int i = 1, x, y; i < n; i++) { 42 scanf("%d%d", &x, &y); 43 add(x, y); 44 add(y, x); 45 } 46 47 DFS(1, 0); 48 49 /// cal Ans 50 sg[1] = 1; 51 sg[2] = 0; 52 for(int i = 3; i <= Ans; i++) { 53 if(std::min(sg[i - 1], sg[i - 2]) == 0) { 54 sg[i] = 1; 55 } 56 else { 57 sg[i] = 0; 58 } 59 } 60 61 if(sg[Ans]) { 62 printf("First\n"); 63 } 64 else { 65 printf("Second\n"); 66 } 67 68 return 0; 69 }
D题意:给你一个黑白矩阵,求它的复杂度。定义一个矩阵的复杂度为:纯色矩阵为0,否则横/竖切一刀,这种划分方式的权值为两个子矩阵的复杂度的max。这个矩阵的复杂度为所有划分方式的权值中的最小值 + 1。n <= 185, 5s。
解:考虑到复杂度不会超过2log,于是设fijkl为左边界为i,上下边界为jk,复杂度为l的矩形右边界最远能到的列。转移的时候有一个非常优秀的单调指针,不知道为什么......
1 #include <bits/stdc++.h> 2 3 const int N = 190; 4 5 short G[N][N], a[N][N][N][18], b[N][N][N][18], sum1[N][N], sum2[N][N]; /// a-> b| 6 char str[N]; 7 8 inline short get1(short l, short r, short i) { /// | 9 return sum1[r][i] - sum1[l - 1][i]; 10 } 11 inline short get2(short i, short l, short r) { /// - 12 return sum2[i][r] - sum2[i][l - 1]; 13 } 14 15 inline void exmax(short &a, const short &b) { 16 a < b ? a = b : 0; 17 return; 18 } 19 inline short Min(const short &a, const short &b) { 20 return a > b ? b : a; 21 } 22 23 int main() { 24 25 26 //printf("%d \n", (sizeof(a) * 2 + sizeof(G) + sizeof(str)) / 1048576); 27 short n, m; 28 scanf("%hd%hd", &n, &m); 29 for(register short i(1); i <= n; ++i) { 30 scanf("%s", str + 1); 31 for(register short j(1); j <= m; ++j) { 32 G[i][j] = (str[j] == '#'); 33 sum1[i][j] = sum1[i - 1][j] + G[i][j]; 34 sum2[i][j] = sum2[i][j - 1] + G[i][j]; 35 //printf("%hd %hd G = %hd \n", i, j, G[i][j]); 36 } 37 } 38 39 for(register short l(1); l <= n; ++l) { 40 for(register short r(l); r <= n; ++r) { 41 short last = -1; 42 for(register short i(m); i >= 1; --i) { 43 short tot(get1(l, r, i)); 44 //printf("tot = %hd \n", tot); 45 if(tot != 0 && tot != r - l + 1) { 46 a[l][r][i][0] = i - 1; 47 last = -1; 48 } 49 else if(last != tot) { 50 a[l][r][i][0] = i; 51 last = tot; 52 } 53 else { 54 a[l][r][i][0] = a[l][r][i + 1][0]; 55 } 56 //printf("a %hd %hd %hd 0 = %hd \n", l, r, i, a[l][r][i][0]); 57 } 58 } 59 } 60 61 /*for(short l = 1; l <= m; l++) { 62 for(short r = l; r <= m; r++) { 63 short last = -1; 64 for(short i = n; i >= 1; i--) { 65 short tot = get2(i, l, r); 66 //printf("tot = %hd \n", tot); 67 if(tot != r - l + 1 && tot != 0) { 68 b[i][l][r][0] = i - 1; 69 last = -1; 70 } 71 else if(tot != last) { 72 b[i][l][r][0] = i; 73 last = tot; 74 } 75 else { 76 b[i][l][r][0] = b[i + 1][l][r][0]; 77 } 78 //printf("b %hd %hd %hd 0 = %hd \n", i, l, r, b[i][l][r][0]); 79 } 80 } 81 }*/ 82 83 if(a[1][n][1][0] == m) { 84 printf("%hd\n", 0); 85 return 0; 86 } 87 88 for(register short j(1); j <= 17; ++j) { 89 90 //printf("------------------- %hd -------------------- \n", j); 91 for(register short i(m); i >= 1; --i) { 92 for(register short l(1); l <= n; ++l) { 93 short p = l; 94 for(register short r(l); r <= n; ++r) { 95 exmax(a[l][r][i][j], a[l][r][i][j - 1]); 96 short t(a[l][r][i][j - 1]); 97 t = a[l][r][t + 1][j - 1]; 98 exmax(a[l][r][i][j], t); 99 if(a[l][r][i][j] == m || l == r) continue; 100 101 for(; p < r; ++p) { 102 /// p [l, p] [p + 1, r] 103 t = Min(a[l][p][i][j - 1], a[p + 1][r][i][j - 1]); 104 // if(a[l][p][i][j - 1] <= a[l][r][i][j]) break; 105 if(a[l][p][i][j - 1] == i - 1) break; 106 if(p == r - 1 || Min(a[l][p + 1][i][j - 1], a[p + 2][r][i][j - 1]) < t) { 107 exmax(a[l][r][i][j], t); 108 break; 109 } 110 } 111 112 } 113 } 114 if(a[1][n][1][j] == m) { 115 printf("%hd\n", j); 116 return 0; 117 } 118 } 119 120 /*for(short l = 1; l <= n; l++) { 121 for(short r = l; r <= n; r++) { 122 for(short i = 1; i <= m; i++) { 123 printf("a %hd %hd %hd = %hd \n", l, r, i, a[l][r][i][j]); 124 } 125 } 126 } 127 printf("--------------- \n"); 128 for(short l = 1; l <= m; l++) { 129 for(short r = l; r <= m; r++) { 130 for(int i = 1; i <= n; i++) { 131 printf("b %hd %hd %hd = %hd \n", i, l, r, b[i][l][r][j]); 132 } 133 } 134 } 135 puts("");*/ 136 } 137 138 /*for(register short i = 0; i <= 17; i++) { 139 if(a[1][n][1][i] == m) { 140 printf("%hd\n", i); 141 break; 142 } 143 if(b[1][1][m][i] == n) { 144 printf("%hd\n", i); 145 break; 146 } 147 }*/ 148 149 return 0; 150 }