BZOJ5029: 贴小广告 & BZOJ5168: [HAOI2014]贴海报

【传送门:BZOJ5029&BZOJ5168


简要题意:

  给出m段区间l[i],r[i],表示l[i]到r[i]的数全部变成i,求出最后有多少种不同的数


题解:

  线段树+离散化

  这是一道经典例题

  先离散化l和r,注意如果离散的时候,两个值相差大于1,就要新加一个值

  然后线段树维护区间颜色就行了


参考代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct trnode
{
    int l,r,lc,rc,c;
}tr[21000];int len;
void bt(int l,int r)
{
    len++;int now=len;
    tr[now].l=l;tr[now].r=r;tr[now].c=-1;
    tr[now].lc=tr[now].rc=-1;
    if(l<r)
    {
        int mid=(l+r)/2;
        tr[now].lc=len+1;bt(l,mid);
        tr[now].rc=len+1,bt(mid+1,r);
    }
}
bool v[1100];
void wen(int now,int l,int r)
{
    if(tr[now].c!=-1)
    {
        v[tr[now].c]=true;
        return ;
    }
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(r<=mid) wen(lc,l,r);
    else if(l>mid) wen(rc,l,r);
    else wen(lc,l,mid),wen(rc,mid+1,r);
}
void change(int now,int l,int r,int k)
{
    if(l==tr[now].l&&r==tr[now].r)
    {
        tr[now].c=k;
        return ;
    }
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(tr[now].c>0)
    {
        tr[lc].c=tr[now].c;
        tr[rc].c=tr[now].c;
    }
    if(r<=mid) change(lc,l,r,k);
    else if(mid<l) change(rc,l,r,k);
    else
    {
        change(lc,l,mid,k);
        change(rc,mid+1,r,k);
    }
    if(tr[lc].c==tr[rc].c&&tr[lc].c!=-1) tr[now].c=tr[lc].c;
    else tr[now].c=-1;
}
struct ask
{
    int l,r,c;
    bool bk;
    ask()
    {
        bk=false;
    }
}A[1100];
struct LSnode
{
    int y,p,op;
}w[2100];int tot;
bool cmp(LSnode n1,LSnode n2){return n1.y<n2.y;}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    tot=0;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&A[i].l,&A[i].r);A[i].c=i;
        if(A[i].l>n) A[i].bk=true;
        if(A[i].r>n) A[i].r=n;
        tot++;w[tot].y=A[i].l,w[tot].p=i;w[tot].op=1;
        tot++;w[tot].y=A[i].r,w[tot].p=i;w[tot].op=2;
    }
    sort(w+1,w+1+tot,cmp);
    int tt=0,mmax=0;
    for(int i=1;i<=tot;i++)
    {
        if(w[i].y!=w[i-1].y) tt++;
        if(w[i].y!=w[i-1].y+1&&w[i].y!=w[i-1].y) tt++;
        if(w[i].op==1) A[w[i].p].l=tt;
        else A[w[i].p].r=tt;
    }
    len=0;bt(1,tt);tr[1].c=-1;
    for(int i=1;i<=m;i++) if(A[i].bk==false) change(1,A[i].l,A[i].r,A[i].c);
    memset(v,false,sizeof(v));
    wen(1,1,tt);
    int ans=0;
    for(int i=1;i<=m;i++) if(v[i]==true) ans++;
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-03-09 12:55  Star_Feel  阅读(189)  评论(0编辑  收藏  举报