• 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
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    经典语录一
    例子二
    例子一
    模板加载
    vim 程序编辑器
    文件与文件系统的压缩,打包与备份
    Linux 磁盘与文件系统管理
    文件与目录操作
    Linux 的文件/目录权限
    Linux 指令代码,热键以及文件放置安排
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8533292.html
Copyright © 2020-2023  润新知