大致题意
n(n<=10000) 个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000)
。求出最后还能看见多少张海报。
Input
第一行: 样例个数T
第二行: 贴海报的人n
第三行: 每个人贴海报的范围
接下来n行:每个人贴海报的范围
思路
由于li,ri的范围很大,需要离散化,但是容易发现,直接离散化会发生一些问题。比如[1,5],[1,2],[4,5]。上述三个区间离散化之后得到的结果是[1,4],[1,2],[3,4],会发现如果按这个顺序挂海报,最终只能看见2副。但实际上区间[1,2]和[4,5]不能完全覆盖[1,5],其中3这个位置仍可以在最后被看见。所以要先对所有的Li,ri进行一些处理,对所有出现的位置排序后,如果
v[i]-v[i-1]>1那么要在中间插一个数字,避免出现上述问题。具体细节见代码。
然后将操作倒序进行,后面的海报有一个优点,当前海报覆盖的区域如果存在空位,那么它一定不可能被前面的海报覆盖了,所以只要区间[li,ri]内的最小值是0,那么ans++。因为这个空位被当前海报最后一个覆盖。所以只要写一个 维护区间最小值的线段树,支持区间赋值操作即可。
代码
#include<cstdio>
#include<algorithm>
#include<ctype.h>
#include<vector>
#include<cstring>
using namespace std;
#define maxn 40005
#define maxm 20006
#define ll long long int
#define INF 0x3f3f3f3f
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
#define mem(a) memset(a,0,sizeof(a))
#define sqr(x) (x*x)
#define inf (ll)2e18+1
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
int T,n,m,a[maxn][2],len,ans;
vector<int>v;
int getid(int x){return lower_bound(v.begin(),v.begin()+len,x)-v.begin()+1;}
int t[maxn<<2],laz[maxn<<2];
void pushdown(int x){
t[x<<1]=t[x<<1|1]=laz[x<<1]=laz[x<<1|1]=1;
laz[x]=0;
}
void pushup(int x){t[x]=min(t[x<<1],t[x<<1|1]);}
void update(int x,int l,int r,int lp,int rp){
if(l<r&&laz[x])pushdown(x);
if(lp<=l&&r<=rp){t[x]=laz[x]=1;return ;}
int mid=(l+r)>>1;
if(lp<=mid)update(x<<1,l,mid,lp,rp);
if(mid+1<=rp)update(x<<1|1,mid+1,r,lp,rp);
pushup(x);
}
int query(int x,int l,int r,int lp,int rp)
{
if(l<r&&laz[x])pushdown(x);
if(lp<=l&&r<=rp)return t[x];
int mid=(l+r)>>1,res=INF;
if(lp<=mid)res=min(res,query(x<<1,l,mid,lp,rp));
if(mid+1<=rp)res=min(res,query(x<<1|1,mid+1,r,lp,rp));
return res;
}
int main(){
T=read();
while(T--){
v.clear();
ans=0;
mem(t);mem(laz);
n=read();
inc(i,1,n){a[i][0]=read();a[i][1]=read();v.push_back(a[i][0]);v.push_back(a[i][1]);}
sort(v.begin(),v.end());
len=unique(v.begin(),v.end())-v.begin();
inc(i,1,len-1)if(v[i]-v[i-1]>1)v.push_back(v[i]-1);
sort(v.begin(),v.end());
len=unique(v.begin(),v.end())-v.begin();
dec(i,n,1){
int x=getid(a[i][0]),y=getid(a[i][1]);
if(query(1,1,len,x,y)==0)ans++;
update(1,1,len,x,y);
}
printf("%d\n",ans);
}
return 0;
}
来源:https://blog.csdn.net/lalalafloat/article/details/100165448