【康复训练】【BZOJ】5168: [HAOI2014]贴海报

Description

Bytetown城市要进行市长竞选,所有的选民可以畅所欲言地对竞选市长的候选人发表言论。为了统一管理,城市委
员 会为选民准备了一个张贴海报的electoral墙。张贴规则如下:
1.electoral墙是一个长度为N个单位的长方形,每个单位记为一个格子;
2.所有张贴的海报的高度必须与electoral墙的高度一致的;
3.每张海报以“A B”表示,即从第A个格子到第B个格子张贴海报;
4.后贴的海报可以覆盖前面已贴的海报或部分海报。
现在请你判断,张贴完所有海报后,在electoral墙上还可以看见多少张海报。

题解

离散。注意离散前要在每个点后面在加一个点。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1006
using namespace std;
inline char nc(){
    static char buf[100000],*i=buf,*j=buf;
    return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
    char ch=nc();int sum=0;
    while(!(ch>='0'&&ch<='9'))ch=nc();
    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
    return sum;
}
int n,N,m,ans;
bool vis[maxn];
struct data{
    int l,r;
}a[maxn];
struct point{
    int x,p,id;
    bool operator <(const point&b)const{return x<b.x;}
}b[maxn*4];
struct nod{
    int l,r,num,tag;
    void add(){
        tag=1;num=r-l+1;
    }
}tree[maxn*16];
void build(int p,int l,int r){
    tree[p].l=l;tree[p].r=r;
    if(l>=r)return;
    int mid=(l+r)>>1;
    build(p<<1,l,mid);build(p<<1|1,mid+1,r);
}
void pushdown(int p){
    if(!tree[p].tag)return;
    tree[p<<1].add();tree[p<<1|1].add();
}
void update(int p,int l,int r){
    if(tree[p].l>r||tree[p].r<l)return;
    if(tree[p].l>=l&&tree[p].r<=r){
        tree[p].add();return;
    }
    pushdown(p);
    update(p<<1,l,r);update(p<<1|1,l,r);
    tree[p].num=tree[p<<1].num+tree[p<<1|1].num;
}
int query(int p,int l,int r){
    if(tree[p].l>r||tree[p].r<l)return 0;
    if(tree[p].l>=l&&tree[p].r<=r)return tree[p].num;
    pushdown(p);
    return query(p<<1,l,r)+query(p<<1|1,l,r);
}
int main(){
    freopen("poster.in","r",stdin);
    freopen("poster.out","w",stdout);
    N=_read();n=_read();
    memset(vis,1,sizeof(vis));
    for(int i=1;i<=n;i++){
        a[i].l=_read(),a[i].r=_read();
        if(a[i].r>N)a[i].r=N;if(a[i].l>N){vis[i]=0;continue;}m++;
        b[m].x=a[i].l,b[m].id=i,b[m].p=0;m++;b[m].x=a[i].r,b[m].id=i,b[m].p=1;
        b[++m].x=a[i].l+1;b[m].p=-1;b[++m].x=a[i].r+1;b[m].p=-1;
    }
    sort(b+1,b+1+m);int p=0;b[0].x=-1;
    for(int i=1;i<=m;i++){
        if(b[i].x>b[i-1].x)p++;
        if(b[i].p==-1)continue;
        if(!b[i].p)a[b[i].id].l=p;
              else a[b[i].id].r=p;
    }
    build(1,1,p);
    for(int i=n;i>=1;i--)if(vis[i]){
        ans+=(query(1,a[i].l,a[i].r)<a[i].r-a[i].l+1);
        update(1,a[i].l,a[i].r);
    }
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值