题意:
给一段长度为10000000的墙贴海报,海报有一个覆盖的范围,后贴的海报可以覆盖先贴的海报。最后询问我们墙上有多少海报显示出来。
题解:
很明显,区间范围太大,直接用线段树的话会超时,我们可以离散化区间,
例如:1~4,4 ~ 8, 1 ~ 8, lsh[1]=1,lsh[2]=4;,lah[3]=8; 那么第一次贴的范围就是1 ~2 ,第二次就是 2 ~3 ,第三次就是 1 ~ 3,最后答案就是1。但是这么离散化是有缺陷的,例如 1 ~8 ,1 ~ 4 ,6 ~8 ,lah[1]=1,lsh[2]=4, lsh[3]=6, lah[4]=8,第一次贴的范围是 1 ~ 4,第二次就是 1 ~ 2,第三次就是 3 ~ 4,这样算出来的答案是2,但实际答案却是 3,所以我们要在范围之差大于1 的元素中再添加一个元素。上面例子就是要在 4和6中再添加一个5(当然还要添加其他的)。离散化之后就可以线段树维护了。
代码:
#include<cstdio>
#include<iomanip>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
const int INF=1e9;
const int MAXN=1e5+5;
int lsh[MAXN];
int lt[MAXN];
int rt[MAXN];
int vis[MAXN];
struct Node
{int l;int r;int sum;
}node[MAXN<<2];
void push_down(int num)
{node[num<<1].sum=node[num].sum;node[num<<1|1].sum=node[num].sum;node[num].sum=-1;
}
void build(int left,int right,int num)
{node[num].l=left;node[num].r=right;node[num].sum=-1;if(left==right){return;}int mid=(left+right)/2;build(left,mid,num<<1);build(mid+1,right,num<<1|1);
}
void updata(int left,int right,int val,int num)
{if(node[num].l>=left&&node[num].r<=right){node[num].sum=val;return;}if(node[num].sum!=-1){push_down(num);}int mid=(node[num].l+node[num].r)>>1;if(right<=mid){updata(left,right,val,num<<1);}else if(left>mid){updata(left,right,val,num<<1|1);}else{updata(left,mid,val,num<<1);updata(mid+1,right,val,num<<1|1);}
}
int ans;
void query(int num)
{if(node[num].sum!=-1&&!vis[node[num].sum]){ans++;vis[node[num].sum]=1;return;}if(node[num].l==node[num].r) return;if(node[num].sum!=-1){push_down(num);}//int mid=(node[num].l+node[num].r)/2;query(num<<1);query(num<<1|1);
}
int main()
{int n;int t;scanf("%d",&t);while(t--){memset(vis,0,sizeof vis);ans=0;scanf("%d",&n);int tot=0;for(int i=1;i<=n;i++){scanf("%d %d",<[i],&rt[i]);lsh[++tot]=lt[i];lsh[++tot]=rt[i];}sort(lsh+1,lsh+1+tot);int pos=unique(lsh+1,lsh+1+tot)-lsh;int tt=pos-1;for(int i=2;i<=pos-1;i++){if(lsh[i]-lsh[i-1]>1){lsh[++tt]=lsh[i-1]+1;}}sort(lsh+1,lsh+1+tt);build(1,tt,1);for(int i=1;i<=n;i++){int p1=lower_bound(lsh+1,lsh+1+tt,lt[i])-lsh;int p2=lower_bound(lsh+1,lsh+1+tt,rt[i])-lsh;updata(p1,p2,i,1);}query(1);printf("%d\n",ans);}
}