chessboard
题意:n*n的矩阵,m次赋值一个子矩阵为c,最后输出答案。
n<=1e3 m<=1e5
解:倒序处理。
拆行处理。
每行内并查集维护未被赋值的地方。
这样每个地方最多被赋值一次,每次修改要访问n行,时间复杂度是O(n(n + m))
1 #include <cstdio> 2 3 inline void read(int &x) { 4 char c = getchar(); 5 x = 0; 6 while(c < '0' || c > '9') { 7 c = getchar(); 8 } 9 while(c >= '0' && c <= '9') { 10 x = (x << 3) + (x << 1) + c - 48; 11 c = getchar(); 12 } 13 return; 14 } 15 16 const int N = 1010, M = 100010; 17 18 struct Node { 19 int opt, c, x, y, xx, yy; 20 }a[M]; 21 22 int n, k, m, fa[M], sv[M], num, path[M], top; 23 char s[10]; 24 25 struct ROW { 26 int a[N], fa[N]; 27 ROW() { 28 for(int i = 1; i < N; i++) { 29 fa[i] = i; 30 a[i] = 1; 31 } 32 } 33 int find(int x) { 34 if(x == fa[x]) { 35 return x; 36 } 37 return fa[x] = find(fa[x]); 38 } 39 inline void change(int v, int l, int r) { 40 int p = find(r); 41 while(p >= l) { 42 a[p] = v; 43 fa[p] = find(p - 1); 44 p = fa[p]; 45 } 46 return; 47 } 48 }row1[N], row2[N]; 49 50 int main() { 51 52 read(n); 53 read(k); 54 read(m); 55 56 for(int i = 1; i <= m; i++) { 57 scanf("%s", s); 58 if(s[0] == 'P') { // print 59 fa[i] = i - 1; 60 a[i].opt = 1; 61 read(a[i].c); 62 read(a[i].x); 63 read(a[i].y); 64 read(a[i].xx); 65 read(a[i].yy); 66 } 67 else if(s[0] == 'S') { // save 68 fa[i] = i - 1; 69 sv[++num] = i; 70 } 71 else { // load 72 int x; 73 //scanf("%d", &x); 74 read(x); 75 fa[i] = sv[x]; 76 } 77 } 78 79 int x = m; 80 while(x) { 81 path[++top] = x; 82 x = fa[x]; 83 } 84 85 for(int e = 1; e <= top; e++) { 86 int i = path[e]; 87 if(!a[i].opt) { 88 continue; 89 } 90 91 for(int j = a[i].x + 1; j <= a[i].xx + 1; j++) { 92 //printf(" j = %d c = %d \n", j, a[i].c); 93 if((a[i].x - 1 + a[i].y) & 1) { 94 row1[j].change(a[i].c, a[i].y + 1, a[i].yy + 1); 95 } 96 else { 97 row2[j].change(a[i].c, a[i].y + 1, a[i].yy + 1); 98 } 99 } 100 } 101 102 for(int i = 1; i <= n; i++) { 103 for(int j = 1; j <= n; j++) { 104 if((i + j) & 1) { 105 printf("%d ", row2[i].a[j]); 106 } 107 else { 108 printf("%d ", row1[i].a[j]); 109 } 110 } 111 puts(""); 112 } 113 return 0; 114 }
说一下原来的题意:
有个矩阵,每次间隔染色一个子矩阵(类似国际象棋那样,左上角要染),还要支持存档/读档。最后一次输出。
1 #include <cstdio> 2 #include <algorithm> 3 4 inline void read(int &x) { 5 char c = getchar(); 6 x = 0; 7 while(c < '0' || c > '9') { 8 c = getchar(); 9 } 10 while(c >= '0' && c <= '9') { 11 x = (x << 3) + (x << 1) + c - 48; 12 c = getchar(); 13 } 14 return; 15 } 16 17 const int N = 1010, M = 100010; 18 19 struct Node { 20 int opt, c, x, y, xx, yy; 21 }a[M]; 22 23 int n, k, m, fa[M], sv[M], num, path[M], top; 24 char s[10]; 25 int sa[N * N * 4], sb[N * N * 4], sc[N * N * 4], sd[N * N * 4]; 26 int tag1[N * N * 4], tag2[N * N * 4], G[N][N]; 27 28 void build(int x, int y, int xx, int yy, int o) { 29 if(x == xx && y == yy) { 30 tag1[o] = 1; 31 return; 32 } 33 int mx = (x + xx) >> 1; 34 int my = (y + yy) >> 1; 35 36 sa[o] = ++num; 37 build(x, y, mx, my, num); 38 39 if(yy > y) { 40 sb[o] = ++num; 41 build(x, my + 1, mx, yy, num); 42 } 43 if(xx > x) { 44 sc[o] = ++num; 45 build(mx + 1, y, xx, my, num); 46 } 47 48 if(yy > y && xx > x) { 49 sd[o] = ++num; 50 build(mx +1, my + 1, xx, yy, num); 51 } 52 return; 53 } 54 55 inline void pushdown(int x, int y, int xx, int yy, int o) { 56 int mx = (x + xx) >> 1; 57 int my = (y + yy) >> 1; 58 if(tag1[o]) { 59 int t = tag1[o]; 60 if(sa[o]) { 61 tag1[sa[o]] = t; 62 } 63 if(sb[o]) { 64 if((my - y + 1) & 1) { 65 tag2[sb[o]] = t; 66 } 67 else { 68 tag1[sb[o]] = t; 69 } 70 } 71 if(sc[o]) { 72 if((mx - x + 1) & 1) { 73 tag2[sc[o]] = t; 74 } 75 else { 76 tag1[sc[o]] = t; 77 } 78 } 79 if(sd[o]) { 80 if((mx - x + my - y + 1) & 1) { 81 tag1[sd[o]] = t; 82 } 83 else { 84 tag2[sd[o]] = t; 85 } 86 } 87 tag1[o] = 0; 88 } 89 if(tag2[o]) { 90 int t = tag2[o]; 91 if(sa[o]) { 92 tag2[sa[o]] = t; 93 } 94 if(sb[o]) { 95 if((my - y + 1) & 1) { 96 tag1[sb[o]] = t; 97 } 98 else { 99 tag2[sb[o]] = t; 100 } 101 } 102 if(sc[o]) { 103 if((mx - x + 1) & 1) { 104 tag1[sc[o]] = t; 105 } 106 else { 107 tag2[sc[o]] = t; 108 } 109 } 110 if(sd[o]) { 111 if((mx - x + my - y + 1) & 1) { 112 tag2[sd[o]] = t; 113 } 114 else { 115 tag1[sd[o]] = t; 116 } 117 } 118 tag2[o] = 0; 119 } 120 return; 121 } 122 123 int X, XX, Y, YY; 124 inline void change(int v, int f, int x, int y, int xx, int yy, int o) { 125 int mx = (x + xx) >> 1; 126 int my = (y + yy) >> 1; 127 if(X <= x && xx <= XX) { 128 if(Y <= y && yy <= YY) { 129 if(f) { 130 tag1[o] = v; 131 } 132 else { 133 tag2[o] = v; 134 } 135 return; 136 } 137 } 138 pushdown(x, y, xx, yy, o); 139 if(X <= mx && Y <= my) { // sa 140 change(v, f, x, y, mx, my, sa[o]); 141 } 142 if(X <= mx && my < YY) { // sb 143 if((my - y + 1) & 1) { 144 change(v, f ^ 1, x, my + 1, mx, yy, sb[o]); 145 } 146 else { 147 change(v, f, x, my + 1, mx, yy, sb[o]); 148 } 149 } 150 if(mx < XX && Y <= my) { // sc 151 if((mx - x + 1) & 1) { 152 change(v, f ^ 1, mx + 1, y, xx, my, sc[o]); 153 } 154 else { 155 change(v, f, mx + 1, y, xx, my, sc[o]); 156 } 157 } 158 if(mx < XX && my < YY) { // sd 159 if((mx - x + my - y + 1) & 1) { 160 change(v, f, mx + 1, my + 1, xx, yy, sd[o]); 161 } 162 else { 163 change(v, f ^ 1, mx + 1, my + 1, xx, yy, sd[o]); 164 } 165 } 166 return; 167 } 168 169 void ed(int x, int y, int xx, int yy, int o) { 170 if(x == xx && y == yy) { 171 G[x][y] = tag1[o]; 172 return; 173 } 174 int mx = (x + xx) >> 1; 175 int my = (y + yy) >> 1; 176 pushdown(x, y, xx, yy, o); 177 ed(x, y, mx, my, sa[o]); 178 if(yy > y) { 179 ed(x, my + 1, mx, yy, sb[o]); 180 } 181 if(xx > x) { 182 ed(mx + 1, y, xx, my, sc[o]); 183 } 184 if(xx > x && yy > y) { 185 ed(mx + 1, my + 1, xx, yy, sd[o]); 186 } 187 return; 188 } 189 190 int main() { 191 192 read(n); 193 read(k); 194 read(m); 195 196 for(int i = 1; i <= m; i++) { 197 scanf("%s", s); 198 if(s[0] == 'P') { // print 199 fa[i] = i - 1; 200 a[i].opt = 1; 201 read(a[i].c); 202 read(a[i].x); 203 read(a[i].y); 204 read(a[i].xx); 205 read(a[i].yy); 206 } 207 else if(s[0] == 'S') { // save 208 fa[i] = i - 1; 209 sv[++num] = i; 210 } 211 else { // load 212 int x; 213 read(x); 214 fa[i] = sv[x]; 215 } 216 } 217 218 int x = m; 219 while(x) { 220 path[++top] = x; 221 x = fa[x]; 222 } 223 std::reverse(path + 1, path + top + 1); 224 num = 1; 225 build(1, 1, n, n, 1); 226 for(int e = 1; e <= top; e++) { 227 int i = path[e]; 228 if(!a[i].opt) { 229 continue; 230 } 231 a[i].x++; 232 a[i].xx++; 233 a[i].y++; 234 a[i].yy++; 235 X = a[i].x; 236 Y = a[i].y; 237 XX = a[i].xx; 238 YY = a[i].yy; 239 if((a[i].x - 1 + a[i].y) & 1) { 240 change(a[i].c, 1, 1, 1, n, n, 1); 241 } 242 else { 243 change(a[i].c, 0, 1, 1, n, n, 1); 244 } 245 } 246 247 248 ed(1, 1, n, n, 1); 249 for(int i = 1; i <= n; i++) { 250 for(int j = 1; j <= n; j++) { 251 printf("%d ", G[i][j]); 252 } 253 puts(""); 254 } 255 return 0; 256 }
这是考场上写的,四分树每次修改貌似是O(n)的,但是卡成6s......只有75分。
话说我第一次写四分树居然是在考场上,而且一个字符都没调就一次写对了......
时间复杂度到底是多少呀......nm的话应该能过呀?莫非是我常数大?