简单说下题意:就是在一个宽1e7墙上面贴n张海报,第i张海报的起点是li,终点是ri,显然海报会覆盖别的海报。问依次贴完n张海报之后最后能看见几张海报。
题目要求最后能看见多少张海报,那么我们将每张海报都分别标上序号1,2,3…n。然后线段树修改区间,最后看线段树最底层有多少种数字即可。
需要注意的几点:
-
海报终点可能到1e7,我们要做的区间修改以及最后桶排计数工作量就会非常大,但是只有20000张海报,我们可以进行离散化,这样最多40000个数据。
-
由于这里的区间修改是完全覆盖原区间
,因此我们更新区间的时候只需更新懒标即可。最后更新完所有区间之后,遍历整棵树,下传所有懒标,再数最底层的不同数字有多少即可。
AC代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define ll long long
#define endl "\n"
#define INF 0x3f3f3f3f
#define MAX 100010
#define mod 1000000007
struct node
{
int l, r, val, k, lazy;
} tr[MAX * 4];
struct node2
{
int l, r;
} p1[MAX];
int p2[MAX * 2];
int ct2 = 1, ct3 = 1;
void build(int k, int l, int r)
{
tr[k].l = l;
tr[k].r = r;
if (l == r)
{
tr[k].val = 0;
return;
}
int mid = (l + r) >> 1;
build(k * 2, l, mid);
build(k * 2 + 1, mid + 1, r);
}
void pushdown(int k)
{
if (tr[k].l == tr[k].r)
{
tr[k].lazy = 0;
return;
}
if (tr[k].lazy)
{
tr[k * 2].lazy = tr[k].lazy;
tr[k * 2 + 1].lazy = tr[k].lazy;
tr[k].lazy = 0;
return;
}
}
void change(int k, int l, int r, int y)
{
if (tr[k].l == l && tr[k].r == r)
{
tr[k].lazy = y;
return;
}
pushdown(k);
int mid = (tr[k].l + tr[k].r) >> 1;
if (r <= mid)
change(k * 2, l, r, y);
else if (l > mid)
change(k * 2 + 1, l, r, y);
else
{
change(k * 2, l, mid, y);
change(k * 2 + 1, mid + 1, r, y);
}
}
int tong[MAX * 2];
void updateans(int k)
{
if (tr[k].lazy)
{
tr[k].val = tr[k].lazy;
tr[k * 2].lazy = tr[k].lazy;
tr[k * 2 + 1].lazy = tr[k].lazy;
}
if (tr[k].l == tr[k].r)
{
tong[tr[k].val] = 1;
return;
}
updateans(k * 2);
updateans(k * 2 + 1);
}
int main()
{
int t;
cin >> t;
while (t--)
{
ct2 = 1, ct3 = 1;
fill(tong, tong + MAX, 0);
fill(p2, p2 + MAX, 0);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &p1[i].l, &p1[i].r);
p2[ct2++] = p1[i].l;
p2[ct2++] = p1[i].r;
}
sort(p2 + 1, p2 + ct2);
int new_end = unique(p2 + 1, p2 + ct2) - p2;
int maxx = 0;
for (int i = 1; i <= n; i++)
{
p1[i].l = lower_bound(p2 + 1, p2 + new_end, p1[i].l) - p2;
p1[i].r = lower_bound(p2 + 1, p2 + new_end, p1[i].r) - p2;
maxx = max(maxx, max(p1[i].l, p1[i].r));
}
build(1, 1, maxx);
int cot = 1;
for (int i = 1; i <= n; i++)
change(1, p1[i].l, p1[i].r, cot++);
updateans(1);
int anss = 0;
for (int i = 1; i <= maxx; i++)
if (tong[i])
anss++;
cout << anss << endl;
}
return 0;
}