题目是依次按给定的范围贴海报,问覆盖到最后还能看到几张海报。
因为给定的贴海报的板子总长度为10^9,数组开不下。但是考虑到海报只有10^5张,而整个问题其实课忽略板子长度,只需要考虑每张海报之间的覆盖关系就可以了,也就是说
(1,1000008)(3,9990)(10,20000000)这三个区间的覆盖情况完全可化成(1,5)(2,4)(3,6),也就是只需要把出现的所有位置进行 排序,把数字转换成对应的序数,这样数组最大 就只需要2*10^5这么大了。另外一个要注意的地方就是海报在区间是连续的,所以节点的意思要改变一下,比如节点左右区间为3和5,离散的区间意思就是3,4,5,这三个点,而连续的区间就是表示(3,5]这段。这样的区别在操作过程中主要体现在结束不再是l==r而应该是r - l <=1,区间分半也不再是(l,m)和(m+1,r)而是(l,m)和(m,r)。
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include<string>
#include <math.h>
#include <set>
#include<map>
#define MOD 1000000007;
using namespace std;
struct node
{
int v;
int l;
int r;
node(int a, int b, int c)
{
v = a;
l = b;
r = c;
lazy = false;
}
node()
{
v = 0;
l = 0;
r = 0;
lazy = false;
}
bool lazy;
};
node ltree[800005];
int z[200005];
int N, Q ,num;
set<int> S;
map<int, int> M;
void creata(int now,int l,int r)
{
ltree[now].l = l;
ltree[now].r = r;
ltree[now].v = 0;
if (l + 1 >= r)
{
return;
}
int m = (l + r >> 1);
creata(now * 2, l, m);
creata(now * 2 + 1, m, r);
return;
}
void find(int now,int l, int r,int v)
{
if (ltree[now].l == l && ltree[now].r == r)
{
ltree[now].lazy = true;
ltree[now].v = v;
return;
}
int m = (ltree[now].l + ltree[now].r >> 1);
if (ltree[now].lazy)
{
ltree[now * 2].lazy = ltree[now * 2 + 1].lazy = true;
ltree[now * 2].v = ltree[now * 2 + 1].v = ltree[now].v;
ltree[now].lazy = false;
}
if (r <= m)
{
find(now * 2, l, r, v);
}
else if (l >= m)
{
find(now * 2 + 1, l, r, v);
}
else
{
find(now * 2, l, m, v);
find(now * 2 + 1, m, r, v);
}
}
void dfs(int now)
{
if (ltree[now].l + 1 >= ltree[now].r)
{
if (ltree[now].v > 0)
S.insert(ltree[now].v);
return;
}
if (ltree[now].lazy)
{
ltree[now * 2].lazy = ltree[now * 2 + 1].lazy = true;
ltree[now * 2].v = ltree[now * 2 + 1].v = ltree[now].v;
ltree[now].lazy = false;
}
dfs(now * 2);
dfs(now * 2 + 1);
}
int main()
{
while (~scanf("%d %d", &N, &Q))
{
S.clear();
M.clear();
for (int i = 1; i <= 2 * N; i = i + 2)
{
scanf("%d %d", &z[i], &z[i + 1]);
S.insert(z[i]);
S.insert(z[i + 1]);
}
num = 0;
for (set<int>::iterator it = S.begin(); it != S.end(); ++it)
{
++num;
M[*it] = num;
}
creata(1, 1, num);
S.clear();
for (int i = 1; i <= 2 * N; i = i + 2)
{
find(1, M[z[i]], M[z[i + 1]], i);
}
dfs(1);
printf("%d\n", S.size());
}
return 0;
}