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

白昼怎懂夜的黑 提交于 2019-11-29 00:49:57

大致题意

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