• 回档|校门外的树3|线段树的应用


    描述
     

       校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
    如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
    K=1,读入l,r表示在l~r之间种上的一种树
    K=2,读入l,r表示询问l~r之间能见到多少种树
    (l,r>0)
    输入格式
    第一行n,m表示道路总长为n,共有m个操作
    接下来m行为m个操作
    输出格式
    对于每个k=2输出一个答案

    备注
    范围:20%的数据保证,n,m<=100
          60%的数据保证,n <=1000,m<=50000
          100%的数据保证,n,m<=50000
    注意:树是可以重叠的,比如1号位置上可以种多种树

    解析:这题可以这么做,建立两棵线段树,分别维护这个点之前有几个左括号和这个点之后有几个右括号,于是就可以做啦。

    代码:
    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    struct node{
        int s,t,l,r;
    }tr[800001];
    int n,q;
    int a[200001];
    
    int read()
    {
        char c=getchar();
        int a=0;
        while (c<'0'||c>'9') c=getchar();
        while (c>='0'&&c<='9')
        {
              a=a*10+c-'0';
              c=getchar();
        }
        return a;
    }
    
    void build(int k,int x,int y)
    {
        tr[k].s=x; tr[k].t=y;
        if (x==y) { tr[k].l=tr[k].r=0; return; }
        int mid=(x+y)>>1;
        build(k<<1,x,mid);
        build(k<<1|1,mid+1,y);
        return;
    }
    
    void insertl(int now,int x,int y)
    {
        int l=tr[now].s,r=tr[now].t;
        //if (y
        if (x==l && y==r)
        {
            tr[now].l+=1;
            return;
        }
        int mid=(l+r)>>1;
        if (x>mid) insertl(now<<1|1,x,y);
            else if (y<=mid) insertl(now<<1,x,y);
                else { insertl(now<<1,x,mid); insertl(now<<1|1,mid+1,y);        }
        return;
    }
    
    void insertr(int now,int x,int y)
    {
        int l=tr[now].s,r=tr[now].t;
        //if (y
        if (x==l && y==r)
        {
            tr[now].r+=1;
            return;
        }
        int mid=(l+r)>>1;
        if (x>mid) insertr(now<<1|1,x,y);
            else if (y<=mid) insertr(now<<1,x,y);
                else { insertr(now<<1,x,mid); insertr(now<<1|1,mid+1,y);        }
        return;
    }
    
    int findl(int k,int x)
    {
        int l=tr[k].s,r=tr[k].t;
        //if (y
        if (l==r) return tr[k].l;
        int mid=(l+r)>>1;
        if (x<=mid) return tr[k].l+findl(k<<1,x);
            else return tr[k].l+findl(k<<1|1,x);
       
    }
    
    int findr(int k,int x)
    {
        int l=tr[k].l,r=tr[k].r;
        if (l==r) return tr[k].r;
        int mid=(l+r)>>1;
        if (x<=mid) return tr[k].r+findr(k<<1,x);
            else return tr[k].r+findr(k<<1|1,x);
    }
    
    int main()
    {
            int total=0;
            n=read();
            build(1,0,n);
            q=read();
            for (int i=1; i<=q; i++)
            {
                int now=read();
                int x=read(),y=read();
                if (now==1)
                {
                    insertl(1,0,x-1);
                    insertr(1,y+1,n);
                    total++;
                }
                else if (now==2)
                {
                    int ans1=findr(1,x);
                    int ans2=findl(1,y);
                    int ans=ans1+ans2;
                    //cout << ans1 << ' ' << ans2 << "hh"  << endl;
                    printf("%lld
    ",total-ans);
                }
            }
            return 0;
    }
  • 相关阅读:
    使用T4为数据库自动生成实体类
    asp.net 下OnClientClick的妙用
    使用缓存的9大误区(上)
    使用缓存的9大误区(下)
    毕业后的五年拉开大家差距的原因在哪里
    mysql字符集
    redhat网络基础配置
    mysql远程连接问题
    Hibernate hql语句修改部分字段
    JQuery使用方法总结
  • 原文地址:https://www.cnblogs.com/Shymuel/p/4393581.html
Copyright © 2020-2023  润新知