Mayor's posters POJ - 2528 (技巧性离散化+线段树)

匿名 (未验证) 提交于 2019-12-02 23:56:01

大致题意

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; }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!