由于这面墙的长度是1e7,所给的范围太大,如果直接建树回超内存,所以考虑用离散化,因为这里只有10000个人,就算是每个人的海报都不相交,最多也就只会用2*n个点;
离散化详解
离散化过后的问题实际上就变成了了区间染色的问题(区间染色问题可以看这个大佬的博客讲的很详细),最开始墙没有贴海报,这里就把lazy全部标记为0,然后区间更新,如果这个区间贴有海报c,就把这个区间的lazy更新为c,全部更新完了之后,我们就可以直接查询区间lazy不等于1的个数,考虑到有重复的情况,所以这里我们直接把lazy放进set里面,最后set的元素个数就是我们要照的答案了
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<vector>
#include<queue>
#include<string>
#include <cmath>
#include<set>
#define mod 999997
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1
#define father l , r , root
#define lowbit(x) ( x & ( - x ) )
using namespace std;
typedef long long ll;
const int maxn = 20010;
const int inf = 0x3f3f3f3f;
int lazy[maxn<<4];
int ql[maxn],qr[maxn];
int all[maxn<<2];
int len;
int n;
int cnt;
set<int>q;
void lisan(){//离散化
sort(all+1,all+1+cnt);
len=unique(all+1,all+1+cnt)-all-1;
for(int i=1;i<=n;i++){
ql[i]=lower_bound(all+1,all+1+len,ql[i])-all;
qr[i]=lower_bound(all+1,all+1+len,qr[i])-all;
}
}
void push_down(int root){
if(lazy[root]==0) return ;
lazy[root<<1]=lazy[root];
lazy[root<<1|1]=lazy[root];
lazy[root]=0;
}
void change(int L,int R,int val,int l,int r,int root){
if(L<=l&&R>=r){
lazy[root]=val;
return ;
}
push_down(root);//这里如果是第一次改动是没有影响的,但如果是第二次改动,就应该吧这个节点再往下移动
int mid=(l+r)>>1;
if(mid>=L)change(L,R,val,lson);
if(mid<R)change(L,R,val,rson);
}
void query(int l,int r,int root){
if(lazy[root]!=0){
q.insert(lazy[root]);
return ;
}
if(l==r) return ;//叶子结点
push_down(root);
int mid=(l+r)>>1;
query(lson);
query(rson);
}
int main( ){
int t;
scanf("%d",&t);
while(t--){
q.clear();
memset(lazy,0,sizeof(lazy));//初始化
scanf("%d",&n);
cnt=0;//不要忘了初始化
for(int i=1;i<=n;i++){
scanf("%d%d",&ql[i],&qr[i]);
all[++cnt]=ql[i];
all[++cnt]=qr[i];
}
lisan();//离散化
for(int i=1;i<=n;i++){
change(ql[i],qr[i],i,1,len,1);
}//区间更新
query(1,len,1);
printf("%d\n",q.size());
}
}