• [swustoj 764] 校门外的树 Plus Plus


    校门外的树 Plus Plus(0764)

    问题描述

    西南某科技大学的校门外长度为 L 的公路上有一排树,每两棵相邻的树之间的间隔都是 1 米。我们可以把马路看成一个数轴,马路的一端在数轴 1 的位置,另一端在 L 的位置;数轴上的每个整数点,即 1,2,……,L,都种有一棵树。

    现在要将这排树的某一段涂成某种颜色,给定 N 组区间[ J,K ],表示从 J 到 K 的树都要涂上一种颜色(每次涂的颜色不一样,而且每次涂色会覆盖掉原来的颜色),区间之间可能有重叠的部分, L 的长度为 1000,0000。现在你的任务是计算涂色工作结束后,这一排树里总共有多少种颜色的树?(没涂过色的不算)

    输入

    第一行为一个整数N (1<=N<=10000)。 接下来的N行每行是两个整数数J,K(1<=J<=K<=1000,0000),表示涂色的起止区间。

    多组测试数据。

    输出

    一个整数,表示有多少种颜色的树。

    样例输入

    2
    1 10
    5 5
    1
    1 1

    样例输出

    2
    1
     
    线段树可解
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 40005
      
    struct tree
    {
        int l,r;
    }p[N<<2];
      
    int tot;
    int ans;
    int x[N];
    int lazy[N<<2];
    bool flag[N<<2];
      
    void pushdown(int rt)
    {
        if(lazy[rt]!=-1)
        {
            lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
            lazy[rt]=-1;
        }
    }
    void build(int l,int r,int rt)
    {
        lazy[rt]=-1;
        if(l==r) return;
        int m=(l+r)>>1;
        build(l,m,rt<<1);
        build(m+1,r,rt<<1|1);
    }
    void update(int l,int r,int rt,int L,int R,int c)
    {
        if(l==L && R==r)
        {
            lazy[rt]=c;
            return;
        }
        pushdown(rt);
        int m=(l+r)>>1;
        if(R<=m) update(l,m,rt<<1,L,R,c);
        else if(L>m) update(m+1,r,rt<<1|1,L,R,c);
        else
        {
            update(l,m,rt<<1,L,m,c);
            update(m+1,r,rt<<1|1,m+1,R,c);
        }
    }
    void query(int l,int r,int rt)
    {
        if(lazy[rt]!=-1)
        {
            if(!flag[lazy[rt]])
            {
                ans++;
                flag[lazy[rt]]=1;
            }
            return;
        }
        if(l>=r) return;
        pushdown(rt);
        int m=(l+r)>>1;
        query(l,m,rt<<1);
        query(m+1,r,rt<<1|1);
    }
    int main()
    {
        int n,i;
        while(scanf("%d",&n)!=EOF)
        {
            ans=0;
            tot=0;
            memset(flag,0,sizeof(flag));
            for(i=0;i<n;i++)
            {
                scanf("%d%d",&p[i].l,&p[i].r);
                x[tot++]=p[i].l;
                x[tot++]=p[i].r;
            }
      
            sort(x,x+tot);
            tot=unique(x,x+tot)-x;
            for(i=tot-1;i>0;i--)
            {
                if(x[i]-x[i-1]>1) x[tot++]=x[i-1]+1;
            }
            sort(x,x+tot);
            build(0,tot-1,1);
            for(i=0;i<n;i++)
            {
                int l=lower_bound(x,x+tot,p[i].l)-x;
                int r=lower_bound(x,x+tot,p[i].r)-x;
                update(0,tot-1,1,l,r,i);
            }
            query(0,tot-1,1);
            cout<<ans<<endl;
        }
        return 0;
    }

    原来搓代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 20005
    
    struct tree
    {
        int l,r;
    }p[N<<2];
    struct node
    {
        int val,id,pos;
    }h[N<<2];
    
    int ans;
    int color[N<<2];
    bool flag[N<<2];
    int change[N<<2];
    
    bool cmp(node a,node b)
    {
        return a.val<b.val;
    }
    void pushup(int rt)
    {
        color[rt]=0;
    }
    void pushdown(int rt)
    {
        if(change[rt]!=-1)
        {
            change[rt<<1]=change[rt<<1|1]=change[rt];
            color[rt<<1]=color[rt<<1|1]=change[rt];
            change[rt]=-1;
        }
    }
    void build(int l,int r,int rt)
    {
        color[rt]=0;
        change[rt]=-1;//初始化
        if(l==r) return;
        int m=(l+r)>>1;
        build(l,m,rt<<1);
        build(m+1,r,rt<<1|1);
    }
    void update(int l,int r,int rt,int L,int R,int c)
    {
        if(l==L && R==r)
        {
            color[rt]=c;
            change[rt]=c;
            return;
        }
        pushdown(rt);
        int m=(l+r)>>1;
        if(R<=m)
            update(l,m,rt<<1,L,R,c);
        else if(L>m)
            update(m+1,r,rt<<1|1,L,R,c);
        else
        {
            update(l,m,rt<<1,L,m,c);
            update(m+1,r,rt<<1|1,m+1,R,c);
        }
        pushup(rt);
    }
    void query(int l,int r,int rt)
    {
        int m=(l+r)>>1;
        if(color[rt])
        {
            if(!flag[color[rt]])
            {
                ans++;
                flag[color[rt]]=1;
            }
            return;
        }
        if(l==r) return; //忘了加这一句、一直RE
        query(l,m,rt<<1);
        query(m+1,r,rt<<1|1);
    }
    int main()
    {
        int n,i;
        while(scanf("%d",&n)!=EOF)
        {
            ans=0;
            memset(flag,0,sizeof(flag));
            for(i=0;i<n;i++)
            {
                scanf("%d%d",&p[i].l,&p[i].r);
                h[i*2].val=p[i].l;
                h[i*2].id=i;
                h[i*2].pos=0;
                h[i*2+1].val=p[i].r;
                h[i*2+1].id=i;
                h[i*2+1].pos=1;
            }
            /* 离散化 */
            sort(h,h+n*2,cmp);
            int last=-1,total=0;
            for(i=0;i<n*2;i++)
            {
                if(h[i].val!=last) 
                {
                    total++;
                    if(i && h[i].val-h[i-1].val>1) total++; //注意这里、= =、手动插点
                    last=h[i].val;
                }
                if(h[i].val!=total)
                {
                    if(h[i].pos) p[h[i].id].r=total;
                    else p[h[i].id].l=total;
                }
            }
            build(1,total,1);
            for(i=0;i<n;i++)
            {
                update(1,total,1,p[i].l,p[i].r,i+1);
            }
            query(1,total,1);
            cout<<ans<<endl;
        }
        return 0;
    }
    趁着还有梦想、将AC进行到底~~~by 452181625
  • 相关阅读:
    gridview填加双击事件
    后台找前台服务器控件,客户端控件方法
    ie缓存是什么 和 清除ie缓存方法
    js 去掉空格的方法
    SQL 用户sa登录失败,该用户与可信sql server连接无关联
    (转)C#里面比较时间大小三种方法
    sql UNION 和 UNION ALL 的区别
    windows 计划任务 打开窗口
    mysql 优化8种方式
    javascript小括号表达式
  • 原文地址:https://www.cnblogs.com/hate13/p/4047820.html
Copyright © 2020-2023  润新知