POJ 2528 Mayor's posters
这一题多数用的是线段树+离散化,但是今天正好看到矩阵切割,所以就用矩阵切割试了一下。
参考了 http://www.2cto.com/kf/201209/156711.html
的代码,进行了一些修改,个人感觉更简洁且比较容易理解。
#include<iostream>
#include<stack>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<cmath>
using namespace std;
const int M = 100000;
const int N = 10000;
struct line
{
int l, r;
int color;
line(int ll = 0, int rr = 0, int c = 0) : l(ll), r(rr), color(c) {}
}post[M], cur;
int tot;
bool used[N];
inline bool cross(const line& l1, const line& l2)
{
return !(
(l1.l > l2.r)
|| (l1.r < l2.l));
}
inline void add(const line& t)
{
post[tot++] = t;
}
void cut(const line& t)
{
if(t.l < cur.l)
{
add(line(t.l, cur.l-1, t.color));
}
if(t.r > cur.r)
{
add(line(cur.r+1, t.r, t.color));
}
}
int main(int argc, char *argv[])
{
#ifdef ACM_LOCAL // Local
freopen("in", "r", stdin);
#else
#ifndef ONLINE_JUDGE // not HDOJ / POJ
freopen("humble.in", "r", stdin);
freopen("humble.out", "w", stdout);
#endif
#endif
int ncase;
scanf("%d", &ncase);
while(ncase--)
{
tot = 0;
int color = 0;
int n;
scanf("%d", &n);
while(n--)
{
scanf("%d %d", &cur.l, &cur.r);
cur.color = color++;
// 倒序,否则在cut操作中增加的线段也会再被检查一遍
for(int i = tot-1; i>= 0; i--)
{
if(cross(post[i], cur))
{
cut(post[i]);
post[i] = post[--tot];
}
}
add(cur);
}
memset(used, false, sizeof(used));
int cnt = 0;
for(int i = 0; i!= tot; i++)
{
if(!used[post[i].color])
{
used[post[i].color] = true;
cnt++;
}
}
printf("%d\n", cnt);
}
return 0;
}
BTW,按说注释中提到的那个循环改成顺序的应该也可以的,只是会慢一些,但实际提交了却是RE。目前还不清楚原因。