SGU 177 解题手记
这题跟USACO的Shaping Regions有相似之处,我曾写过一篇解题报告:http://www.studentblog.net/m/bslgh/archives/2006/usaco211.html。
采用倒序染色+封闭然过色的格子的办法。对每一行开一个链表,染色时将白色部分记入总和,染色过后将这个格子删去。由于每个格子只被染色一次,所以总复杂度能控制在O(n^2)级别。
Submit 1: TLE on 13。废弃STL的list不用,改设置一个next数组来表示。
调试过程中出现了一个很奇怪的状况,程序在给出输出,return 0之后又出现了“段错误”。大概是读数据的时候有问题。
Submit 2: WA on 2。next数组只需要开一行就可以了。在封闭格子的时候出错了,假设之前染色[2,10],当下一次染色[1,6]的时候,我把[1,7]封闭起来了。
Submit 3: TLE on 13。实际上根据前面的做法,复杂度无法控制在O(n^2)级别。极端数据是5000个给最后一列染色。问题出在每次都从链表头开始寻找染色的格子,现在需要更直接的定位方法。
Submit 4: AC。143ms,第一名(2008-01-29 19:29:20),拍照留念。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int main() { int next[1002]; bool painted[1001]; int ops[5000][5]; int n,m,tot; scanf("%d %d",&n,&m); tot=n*n; for (int i=0;i<m;++i) { int x1,x2,y1,y2; char c; scanf("%d %d %d %d %c",&x1,&y1,&x2,&y2,&c); ops[i][0]=min(x1,x2); ops[i][2]=max(x1,x2); ops[i][1]=min(y1,y2); ops[i][3]=max(y1,y2); ops[i][4]=c=='b'; } for (int i=1;i<=n;++i) { for (int j=0;j<=n;++j) next[j]=j+1; next[n+1]=n+1; memset(painted,false,sizeof(painted)); for (int p=m-1;p>=0;--p) if (i>=ops[p][0] && i<=ops[p][2]) { int s,j; for (j=ops[p][1];j<=ops[p][3];s=j,j=next[j],next[s]=next[ops[p][3]]) if (!painted[j]) { tot-=ops[p][4]; painted[j]=true; } } } printf("%d\n",tot); return 0; } |
