线段树 划分树 树状数组

线段树    利用数组来维护一个类似前缀和的区间和  在查询的时候查这个区间数组    特殊操作   有延时标记  在区间数组上增加基本不改变原来数组    以达到节省时间的目的   

树状数组  和线段树类似    一个用一个数组维护类似前缀和的东西   但  是   它维护的是一个用二进制表示的前缀和  举个例子  1是1、2是1 2、3是3、4是1 2 3 4、5是5、6 是5 6、7是7、8是1 2 3 4 5 6 7 8 

划分数    用两个二位数组  来查找区间内第几大的数     第一个数组是存数的  另一个是用来存前i个有几个进入了左侧 还有 数组是对半分的  每次下一层都是上层区间对半分  


LL tree0[1000000];
LL tree11[20][1000000];
LL tree12[20][1000000];
void build_tree(LL x,LL y,LL n)
{
    if(x==y)
    {
        return ;
    }
    LL sum=y-x+1;
    LL mid=(x+y)>>1;
    LL max1=tree0[mid];
    LL right=0,left=0;
    for(i=x;i<=y;i++)
    {
        if(tree11[n][i]<max1)
            sum--;
    }
    for(i=x;i<=y;i++)
    {
        if(x==i)
            tree12[n][i]=0;
        else
            tree12[n][i]=tree12[n][i-1];
        if(tree11[n][i]<max1||(tree11[n][i]==max1&&sum))
        {
            tree12[n][i]++;
            tree11[n+1][x+(right++)]=tree11[n][i];
        }
        else
        {
            tree11[n+1][mid+(left++)]=tree11[n][i];
        }
    }
    build_tree(x,mid,n+1);
    build_tree(mid+1,n+1);
}
LL querty(LL x,LL y,LL qx,LL qy,LL k,LL n)
{
    if(qx==qy)
        return tree11[n][qx];
    LL mid=(x+y)>>1;
    LL left;
    Ll qleft;
    if(x==qx)
        left=0;
    else
        left=tree12[n][qx-1];
    qleft=tree12[n][qy]-left;
    if(qleft>=k)
    {
        LL newx=x+left;
        LL newy=newx+qleft-1;
        querty(x,y,newx,newy,k,n+1);
    }
    else
    {
        LL newx=mid+qx-x+1-left;
        LL newy=newx+qy-qx+1-qleft-1;
        querty(mid+1,y,newx,newy,k-qleft,n+1);
    }
}
线段树 
#define length node[i].r-node[i].l+1
struct qwe{
ll r,l;
ll mid()
{
    return (r+l)/2;
}
};
ll upup(ll i)
{
    node[i].v=node[i<<1].v+node[i<<1|1].v;
}
ll build_tree(ll i,ll l,ll r)
{
    node[i].r=r;
    node[i].l=l;
    if(node[i].r==node[i].l)
    {
        sum[i]=1;
        add[i]=0;
        return ;
    }
    ll m=node[i].mid();
    build_tree(i<<1,l,m);
    build_tree(i<<1|1,m+1,r);
    upup(i);
}
ll updown(ll i,ll lenth)
{
    if(add[i])
    {
        add[i<<1]+=add[i];
        add[i<<1|1]+=add[i];
        sum[i<<1]+=add[i]*(lenth-(lenth>>1));
        sum[i<<1|1]+=add[i]*(lenth>>1);
        add[i]=0;
    }
}
ll update(ll l,ll r,ll i,ll v)
{
    if(l==node[i].l&&node[i].r)
    {
        sum[i]+=v*(r-l+1);
        add[i]+=v;
    }
    updown(i,length);
    ll mid=node[i].mid();
    if(r<=mid)
    {
        update(l,r,i<<1,v);
    }
    else
    {
        if(l>mid)
        {
            update(l,r,i<<1|1,v);
        }
        else
        {
            update(l,mid,i<<1,v);
            update(mid+1,r,i<<1|1,v);
        }
    }
}
ll querty(ll i,ll l,ll r)
{
    if(l==node[i].l&&node[i].r)
    {
        m+=sum[i];
    }
    updown(i,length);
    //两种书写方式都行
    i=i<<1;
    if(node[i].r>=l)
    {
        if(node[i].r>=r)
        {
            querty(i,l,r);
        }
        else
            querty(i,l,node[i].r);
    }
    i++;
    if(node[i].l<=r)
    {
        if(l>=node[i].l)
        {
            querty(i<<1|1,l,r);
        }
        else
            querty(i<<1,node[i].l,r);
    }
    //第二种
    ll mid=node[i].mid();
    if(mid>=r)
    {
        querty(i<<1,l,r);
    }
    else
    {
        if(mid<l)
        querty(i<<1|1,l,r);
        else
        {
            querty(i<<1,l,mid);
            querty(i<<1|1,mid+1,r);
        }
    }
}

ll lowbit(ll i)
{
    return i&(-i);
}
ll update(ll i,ll a)
{
    while(i<=n)
    {
        c[i]+=a;
        i+=lowbit(i);
    }
}
ll getsum(ll i)
{
    ll  sum=0;
    while(i>0)
    {
        sum+=c[i];
        i-=lowbit(i);
    } 
    return sum;
}

猜你喜欢

转载自blog.csdn.net/qq_41886199/article/details/82668895
今日推荐