原题地址:http://poj.org/problem?id=2528
原题地址:贴海报,后面的海报可以贴在前面的海报的上面,按给定的顺序在区间为(l,r)的位置去贴海报,问最后可以在表面看见的海报有多少张
这题调bug调的我心态崩了。说一下我的问题
1.当用非结构体写法写线段树的时候,并且要像这题一样使用离散化,那么你就格外需要注意在updata或者query函数里面传进去的值了
void update(int L, int R, int l, int r, int rt, int color)//函数定义
update(l, r, 1, k, 1, i + 1);
/*传参,贴别需要注意的是传进去的第三个参数k,这是经过离散化的数值的种类,也就是说线段树的大小,当初就是因为没注意把k一直写成了n,一直错*/
还有一点就是在使用lower_bound这个函数的时候,要注意离散化的坐标是要从1开始的
l = lower_bound(c, c + k, le[i]) - c +1;//就像这样
l = lower_bound(a+1, a+A+1, l[i]) - a;//或者这样
下面贴代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#define mid (l+r)/2
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int maxn = 2e4 + 5;
int col[maxn << 2], vis[maxn];
int le[maxn], ri[maxn], c[maxn << 2], ans;
void pushdown(int rt) {
if(col[rt] == -1) return;
col[rt << 1] = col[rt << 1 | 1] = col[rt];
col[rt] = -1;
}
void update(int L, int R, int l, int r, int rt, int color) {
if(l >= L && r <= R) {
col[rt] = color;
return;
}
pushdown(rt);
if(L <= mid) update(L, R, lson, color);
if(R > mid) update(L, R, rson, color);
}
void query( int l, int r, int rt) {
if(col[rt] != -1) {
if(!vis[col[rt]]) {
vis[col[rt]] = 1;
++ans;
}
return;
}
query(lson);
query(rson);
}
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;
/*还有要注意插格子具体参考这篇博客https://blog.csdn.net/pmt123456/article/details/53492553*/
}
sort(c, c + k);
return unique(c, c + k) - c;
}
int main() {
int cas, n, k, l, r;
scanf("%d", &cas);
while(cas--) {
scanf("%d", &n);
for(int i = 0; i < n; ++i) scanf("%d%d", &le[i], &ri[i]);
k = compress(n);//去重确定元素个数,以便用于建树以及更新
ans = 0;
memset(vis, 0, sizeof(vis));
memset(col, 0, sizeof(col));
for(int i = 0; i < n; ++i) {
l = lower_bound(c, c + k, le[i]) - c + 1; //+1是因为线段树离散化范围要从1开始
r = lower_bound(c, c + k, ri[i]) - c + 1;
update(l, r, 1, k, 1, i + 1);//线段树的最大范围是k,是经过离散化后的数值种类
}
vis[0] = 1;
query(1, k, 1);
printf("%d\n", ans);
}
return 0;
}