求助fhqtreap就对了一个点。。

P3372 【模板】线段树 1

laplace_oo @ 2022-10-29 08:05:18

/// @brief FHQ Treap
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,m,a[N];
int root,cnt;
int lc[N],rc[N],siz[N];
int val[N],sum[N],key[N],tag[N];
void add(int p,int k)
{
    sum[p]+=siz[p]*k;
    tag[p]+=k;
    val[p]+=k;
}
void up(int p)
{
    siz[p]=siz[lc[p]]+siz[rc[p]]+1;
    sum[p]=sum[lc[p]]+sum[rc[p]]+val[p];
}
int neo(int v)
{
    cnt++;
    val[cnt]=v;
    key[cnt]=rand();
    siz[cnt]=1;
    return cnt;
}
void dwd(int p)
{
    if(lc[p])
    {
        sum[lc[p]]+=siz[lc[p]]*tag[p];
        val[lc[p]]+=tag[p];
        tag[lc[p]]+=tag[p];
    }
    if(rc[p])
    {
        sum[rc[p]]+=siz[rc[p]]*tag[p];
        val[rc[p]]+=tag[p];
        tag[rc[p]]+=tag[p];
    }
    tag[p]=0;
}
void split(int p,int &x,int &y,int k)
{
    if(!p)
    {
        x=y=0;
        return;
    }
    dwd(p);
    if(siz[lc[p]]+1<=k)
    {
        x=p;
        split(rc[p],rc[x],y,k-siz[lc[p]]-1);
    }
    else
    {
        y=p;
        split(lc[p],x,lc[y],k);
    }
    up(p);
}
int merge(int x,int y)
{
    if(!x||!y)return x|y;
    dwd(x);
    dwd(y);
    if(key[x]<=key[y])
    {
        rc[x]=merge(rc[x],y);
        up(x);
        return x;
    }
    else
    {
        lc[y]=merge(x,lc[y]);
        up(y);
        return y;
    }
}
int build(int l,int r)
{
    if(l==r)return neo(a[l]);
    int mid=(l+r)>>1;
    return merge(build(l,mid),build(mid+1,r));
}
void addrange(int l,int r,int k)
{
    int x,y,z;
    split(root,x,y,r);
    split(x,x,z,l-1);
    add(z,k);
    root=merge(x,merge(z,y));
}
int askrange(int l,int r)
{
    int x,y,z;
    split(root,x,y,r);
    split(x,x,z,l-1);
    int res=sum[z];
    root=merge(x,merge(z,y));
    return res;
}
signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;++i)
    {
        scanf("%lld",&a[i]);
    }
    root=build(1,n);
    for(int i=1;i<=m;++i)
    {
        int o,x,y;
        scanf("%lld%lld%lld",&o,&x,&y);
        if(o==1)
        {
            int k;
            scanf("%lld",&k);
            addrange(x,y,k);
        }
        else
        {
            printf("%lld\n",askrange(x,y));
        }
    }
    return 0;
}

by 淸梣ling @ 2022-10-29 08:21:32

你可以尝试线段树


by 淸梣ling @ 2022-10-29 08:28:36

@Lake____ 你 neo sum 没更新


by laplace_oo @ 2022-10-29 08:41:40

@淸梣ling 过了,谢谢


|