这一题多数用的是线段树+离散化,但是今天正好看到矩阵切割,所以就用矩阵切割试了一下。
参考了
http://www.2cto.com/kf/201209/156711.html
的代码,进行了一些修改,个人感觉更简洁且比较容易理解
View Code
1 #include<iostream> 2 #include<stack> 3 #include<cstring> 4 #include<cstdio> 5 #include<queue> 6 #include<algorithm> 7 #include<set> 8 #include<map> 9 #include<vector> 10 #include<cmath> 11 using namespace std; 12 const int M = 100000; 13 const int N = 10000; 14 15 struct line 16 { 17 int l, r; 18 int color; 19 line(int ll = 0, int rr = 0, int c = 0) : l(ll), r(rr), color(c) {} 20 }post[M], cur; 21 int tot; 22 23 bool used[N]; 24 25 inline bool cross(const line& l1, const line& l2) 26 { 27 return !( 28 (l1.l > l2.r) 29 || (l1.r < l2.l)); 30 } 31 32 inline void add(const line& t) 33 { 34 post[tot++] = t; 35 } 36 37 void cut(const line& t) 38 { 39 if(t.l < cur.l) 40 { 41 add(line(t.l, cur.l-1, t.color)); 42 } 43 if(t.r > cur.r) 44 { 45 add(line(cur.r+1, t.r, t.color)); 46 } 47 } 48 49 50 int main(int argc, char *argv[]) 51 { 52 #ifdef ACM_LOCAL // Local 53 freopen("in", "r", stdin); 54 #else 55 #ifndef ONLINE_JUDGE // not HDOJ / POJ 56 freopen("humble.in", "r", stdin); 57 freopen("humble.out", "w", stdout); 58 #endif 59 #endif 60 61 int ncase; 62 scanf("%d", &ncase); 63 while(ncase--) 64 { 65 tot = 0; 66 int color = 0; 67 int n; 68 69 scanf("%d", &n); 70 while(n--) 71 { 72 scanf("%d %d", &cur.l, &cur.r); 73 cur.color = color++; 74 75 // 倒序,否则在cut操作中增加的线段也会再被检查一遍 76 for(int i = tot-1; i>= 0; i--) 77 { 78 if(cross(post[i], cur)) 79 { 80 cut(post[i]); 81 post[i] = post[--tot]; 82 } 83 } 84 add(cur); 85 } 86 87 memset(used, false, sizeof(used)); 88 int cnt = 0; 89 for(int i = 0; i!= tot; i++) 90 { 91 if(!used[post[i].color]) 92 { 93 used[post[i].color] = true; 94 cnt++; 95 } 96 } 97 98 printf("%d\n", cnt); 99 } 100 101 return 0; 102 }
BTW,按说注释中提到的那个循环改成顺序的应该也可以的,只是会慢一些,但实际提交了却是RE。目前还不清楚原因

浙公网安备 33010602011771号