• HDU 5372 线段树


    给出两种操作:

    第i个0:在x位置插入一个长度为i的线段,并输出该线段共覆盖了多少之前增加的线段

    1:删除第i次插入的线段

    官方题解:对于新插入的线段,查询有多少个线段左端点大于等于该线段的左端点。 再查询有多少个线段的右端点大于该线段右端点, 两者之差就是答案。用两个树状数组搞定。时间复杂度nlog


    思路非常好理解,直接用一个线段树记录区间的左端点和右端点就可以

    #include "stdio.h"
    #include "string.h"
    #include "algorithm"
    using namespace std;
    const int inf=0x7fffffff;
    struct A
    {
        int op,l,r,x;
    } a[400010];
    
    struct Y
    {
        int x,id;
    } y[400010];
    
    struct Data
    {
        int l,r,a,b;
    } data[1600010];
    
    bool cmp(Y a,Y b)
    {
        return a.x<b.x;
    }
    
    void build(int l,int r,int k)
    {
        data[k].l=l;
        data[k].r=r;
        data[k].a=data[k].b=0;
        if (l==r) return ;
    
        int mid=(l+r)/2;
    
        build(l,mid,k*2);
        build(mid+1,r,k*2+1);
    }
    
    int query(int l,int r,int k,int op)
    {
        if (l>r) return 0;
        if (data[k].l==l && data[k].r==r)
        {
            if (op==1) return data[k].a;
            else return data[k].b;
        }
    
        int mid=(data[k].l+data[k].r)/2;
    
        if (r<=mid) return query(l,r,k*2,op);
        else if (l>mid) return query(l,r,k*2+1,op);
        else  return query(l,mid,k*2,op)+query(mid+1,r,k*2+1,op);
    }
    
    void updata(int n,int k,int op,int x)
    {
        if (op==1) data[k].a+=x;
        else data[k].b+=x;
    
        if (data[k].l==n && data[k].r==n) return ;
    
        if (n<=data[k*2].r) updata(n,k*2,op,x);
        else updata(n,k*2+1,op,x);
    }
    
    int main()
    {
        int Case,n,i,x,cnt;
        Case=1;
        while (scanf("%d",&n)!=EOF)
        {
            cnt=1;
    
            for (i=0; i<n; i++)
            {
                scanf("%d",&a[i].op);
                if (a[i].op==0)
                {
                    scanf("%d",&a[i].l);
                    a[i].r=a[i].l+cnt;
                    cnt++;
                }
                else
                {
                    scanf("%d",&x);
                    x--;
                    a[i].x=x;
                }
                y[i*2].x=a[i].l;
                y[i*2].id=-i-1;
                y[i*2+1].x=a[i].r;
                y[i*2+1].id=i+1;
    
            }
            sort(y,y+n*2,cmp);
            cnt=0;
            if (y[0].id<0)
                a[-y[0].id-1].l=0;
            else
                a[y[0].id-1].r=0;
    
            for (i=1; i<n*2; i++)
            {
                if (y[i].x!=y[i-1].x) cnt++;
                if (y[i].id<0) a[-y[i].id-1].l=cnt;
                else a[y[i].id-1].r=cnt;
            }
    
            build(0,cnt,1);
    
            printf("Case #%d:
    ",Case++);
            int temp=0;
            for (i=0; i<n; i++)
            {
                if (a[i].op==0)
                {
                    printf("%d
    ",query(a[i].l,cnt,1,1)-query(a[i].r+1,cnt,1,2));
                    updata(a[i].l,1,1,1);
                    updata(a[i].r,1,2,1);
                    a[temp].l=a[i].l;
                    a[temp].r=a[i].r;
                    temp++;
                }
                else
                {
                    updata(a[a[i].x].l,1,1,-1);
                    updata(a[a[i].x].r,1,2,-1);
                }
    
            }
        }
    
        return 0;
    }
    


  • 相关阅读:
    JAVA_集合_作业01
    Java_Objects_hashCode
    Java成员内部类
    Java集合练习_实现购物车需求
    Java初级_单例设计模式
    HelloWorld
    vue中视频标点
    防抖节流?俩者区别?vue如何使用防抖、节流来解决点击问题?
    keep-alive
    axios和ajax的区别
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7001660.html
Copyright © 2020-2023  润新知