题意:
在一个墙上贴海报,给你每次贴海报的左边起点,和右边的终点,如果有重叠的部分,后贴的会覆盖前面贴上去的那部分。问最后从正面上看,能看到多少张。
思路:
我们可以把整面墙看成一条线段,每次贴海报都是对线段的一次染色,每次染不同的色。最后查找有多少种颜色在这条线段上,这个问题就解决了。
首先需要解决数据的问题,由于本题的数据范围很大,但是我们注意到,他的线段个数很少,所以我们利用这一点,对数据进行离散化。
离散化:
1.先把所有的数都放到一个数组里面。
2.对这个数组进行排序。
3.然后依次对每个数编号
4.对数组的值和下标作一个映射。
但是由于离散化的是一个区间,所以如果按照上面正常的离散化就会出现问题:
1 10
1 4
6 10
这样我们离散化出来的是:1 4 6 10
0 1 2 3
在进行操作的时候,操作的是 0 - 3、0 - 1、2 - 3,这样看上去就会是填满了整条线段,但实际上4 - 6 中间会有一个点被忽略了。
所以,我们在上面的操作2后再加一步,在两个不相邻数的中间加一个数,来使数据的表达完整。
刚才的例子:就可以变成 1 2 4 5 6 10
0 1 2 3 4 5
这样就能做到无遗漏。
其余的就是线段树插线操作了,还是延时标记。
Code:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<set>
#include<map>
#include<cctype>
#include<vector>
//#define TEST
#define LL long long
#define Mt(f, x) memset(f, x, sizeof(f));
#define rep(i, s, e) for(int i = (s); i <= (e); ++i)
#ifdef TEST
#define See(a) cout << #a << " = " << a << endl;
#define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl;
#define debug(a, s, e){ rep(_i, s, e) {cout << a[_i] << ' '; }cout << endl;}
#define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee);}
#else
#define See(a)
#define See2(a, b)
#define debug(a, s, e)
#define debug2(a, s, e, ss, ee)
#endif
const int MAX = 2e9;
const int MIN = -2e9;
const int PI = acos(-1.0);
const double eps = 1e-8;
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int N = 20000 + 5;
int f[N << 4];
int l[N], r[N];
int a[N << 3];
bool v[N << 3];
int ans;
void pushDown(int rt)
{
if(f[rt])
{
f[rt << 1] = f[rt << 1 | 1] = f[rt];
f[rt] = 0;
}
}
void update(int L, int R, int x, int l, int r, int rt)
{
if(l >= L && r <= R)
{
f[rt] = x;
return ;
}
pushDown(rt);
int m = (l + r) >> 1;
if(L <= m) update(L, R, x, lson);
if(R > m) update(L, R, x, rson);
}
void pushAll(int l, int r, int rt)
{
if(f[rt])
{
if(!v[f[rt]])
{
++ans;
v[f[rt]] = true;
}
}
if(l == r)
{
return ;
}
pushDown(rt);
int m = (l + r) >> 1;
pushAll(lson);
pushAll(rson);
}
int mp(int key, int n, int a[])
{
return upper_bound(a, a + n, key) - a;
}
int main()
{
int T;
cin >> T;
while(T--)
{
Mt(v, false);
Mt(f, 0);
int n;
scanf("%d", &n);
int num = 0;
for(int i = 0; i < n; ++i)
{
scanf("%d%d", &l[i], &r[i]);
a[num++] = l[i];
a[num++] = r[i];
}
sort(a, a + num);
num = unique(a, a + num) - a;
int newNum = num;
for(int i = 1; i < num; ++i)
{
if(a[i] != a[i - 1] + 1)
{
a[newNum++] = a[i - 1] + 1;
}
}
num = newNum;
sort(a, a + num);
debug(a, 0, num - 1);
for(int i = 0; i < n; ++i)
{
update(mp(l[i], num, a), mp(r[i], num, a), i + 1, 0, num, 1);
}
ans = 0;
pushAll(0, num, 1);
printf("%d\n", ans);
}
return 0;
}