大致题意
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; } 来源:51CTO
作者:lalalafloat
链接:https://blog.csdn.net/lalalafloat/article/details/100165448