题意:
n(n<=10000) 个人依次贴海报,给出每张海报所贴的范围li 、ri(1<=li<=ri<=10000000)。求出最后还能看见多少张海报。
思路:
线段树区间更新题,可以用懒人更新的思路优化,对于线段树来说10000000显然太大,数组开不了,而n只有10000,就可以离散化一下。
但是离散化对本题来说有一个问题(坑), 就是由于我们是紧紧挨着压缩的, 所以可能会存在错误覆盖的问题
例如对于数据
3
1 10
1 3
7 10
我们压缩过后应该就变为
1 4
1 2
3 4
可这样的话我们目测一下, 就只有2个区间可以看到了, 第一个被盖住了. 而真正的答案应该是3才对
这是我们应该在离散化数组c中存储时考虑将每次的右边界r+1也存入, 这样就可以有效避免错误覆盖的问题。
问题code:
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5;
int st[maxn * 4], vis[maxn * 2], cnt[maxn * 2], a[maxn * 2];
int ans;
void pushdown(int o){ //懒人更新
if(st[o]) st[o << 1] = st[o << 1 | 1] = st[o], st[o] = 0;
}
void updata(int o, int l, int r, int L, int R,int res){
if(l >= L && r <= R){
st[o] = res;
return;
}
int m = (l + r) >> 1;
pushdown(o);
if(L <= m) updata(o << 1, l, m, L, R, res);
if(R > m) updata(o << 1 | 1, m + 1, r, L, R, res);
}
void query(int o, int l, int r){
if(st[o]) {
if(!vis[st[o]] && st[o] != 0){
vis[st[o]] = 1;
ans++;
}
return;
}
if(l == r) return ;
int m = (l + r) >> 1;
pushdown(o);
query(o << 1, l, m);
query(o << 1 | 1, m + 1, r);
}
int main(){
int c, n;
scanf("%d", &c);
while(c--){
scanf("%d", &n);
int cot = 0;
for(int i = 0; i < n; i++){
scanf("%d%d", &cnt[i * 2], &cnt[i * 2 + 1]);
a[cot++] = cnt[i * 2];
a[cot++] = cnt[i * 2 + 1];
a[cot++] = cnt[i * 2 + 1] + 1;
}
sort(a, a + cot);
int tot = (int)(unique(a, a + cot) - a); //unique函数返回值为第一个重复元素的指针
for(int i = 0; i < 2 * n; i++)
cnt[i] = (int)(lower_bound(a, a + cot, cnt[i]) - a + 1);
ans = 0; //初始化
fill(vis, vis + 2 * tot + 1, 0);
fill(st, st + 4 * tot + 1, 0);
for(int i = 0; i < n; i++){
updata(1, 1, tot, cnt[i * 2], cnt[i * 2 + 1], i + 1);
}
query(1, 1, tot);
printf("%d\n", ans);
}
}
正确code:
#include<iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lc p<<1,s,mid
#define rc p<<1|1,mid+1,e
#define mid ((s+e)>>1)
#define CLR(A) memset(A,0,sizeof(A))
using namespace std;
const int N = 20005;
int col[N * 4], vis[N];
int le[N], ri[N], c[N * 2], ans;
void pushdown(int p)
{
if(col[p] == -1) return;
col[p << 1] = col[p << 1 | 1] = col[p];
col[p] = -1;
}
void update(int p, int s, int e, int l, int r, int v)
{
if(s >= l && e <= r)
{
col[p] = v;
return;
}
pushdown(p);
if(l <= mid) update(lc, l, r, v);
if(r > mid) update(rc, l, r, v);
}
void query(int p, int s, int e)
{
if(col[p] != -1)
{
if(!vis[col[p]])
vis[col[p]] = 1, ++ans;
return;
}
query(lc);
query(rc);
}
int compress(int n) //离散化
{
int k = 0;
for(int i = 0; i < n; ++i)
{
c[k++] = le[i];
c[k++] = ri[i];
c[k++] = ri[i] + 1;
}
sort(c, c + k);
return unique(c, c + k) - c - 1;
}
int main()
{
int cas, m, n, l, r;
scanf("%d", &cas);
while(cas--)
{
scanf("%d", &m);
for(int i = 0; i < m; ++i)
scanf("%d%d", &le[i], &ri[i]);
n = compress(m);
cout << "n = " << n << endl;
ans = 0;
CLR(col), CLR(vis);
for(int i = 0; i < m; ++i)
{
l = lower_bound(c, c + n, le[i]) - c + 1;
r = lower_bound(c, c + n, ri[i]) - c + 1;
update(1, 1, n, l, r, i + 1);
}
vis[0] = 1;
query(1, 1, n);
printf("%d\n", ans);
}
return 0;
}
来源:CSDN
作者:多行不译必自闭
链接:https://blog.csdn.net/dajiangyou123456/article/details/104443727