这一题多数用的是线段树+离散化,但是今天正好看到矩阵切割,所以就用矩阵切割试了一下。

参考了

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。目前还不清楚原因