西安段素围护澄茶树列

澄茶树列的公式弄我的好恶心呀。

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
    int val;//和
    int fir;//首项
    int pub;//公差
};
node t[100000];
int base[100000];
void push_up(int root)
{
    t[root].val=t[root<<1].val+t[root<<1|1].val;
    return ;//处理和
}
void push_down(int root,int l,int m,int r)
{
    t[root<<1].fir+=t[root].fir;//处理首项,将等差数列拆分
    t[root<<1|1].fir+=(t[root].fir+t[root].pub*(m-l+1));
    t[root<<1].pub+=t[root].pub;//处理公差
    t[root<<1|1].pub+=t[root].pub;
    t[root<<1].val+=t[root].fir*(m-l+1)+t[root].pub*(m-l+1)*(m-l)/2;//使用等差数列的公式计算左右区间的和
    t[root<<1|1].val+=t[root].fir*(r-m)+t[root].pub*(m-l+1+r-l)*(r-m)/2;//如果看的乱的话,可以不看我的,自己手推一波
    t[root].fir=0;//置空
    t[root].pub=0;
    return ;
}//下放标记
void build(int root,int l,int r)
{
    if(l==r)
    {
        t[root].val=base[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(root<<1,l,mid);
    build(root<<1|1,mid+1,r);
    push_up(root);
    return ;
}//很简单的建树
void change(int root,int l,int r,int al,int ar,int num,int k)
{
    if(l>=al&&r<=ar)
    {
        t[root].val+=(num*(r-l+1)+k*(r-l+1)*(r-l)/2);
        t[root].fir+=num;
        t[root].pub+=k;
        return ;
    }
    int mid=(l+r)>>1;
    push_down(root,l,mid,r);
    int chg=num+k*(mid-al+1);
    if(mid>=al&&mid+1<=ar)  //最恶心的改变,需要判断分裂的左右区间是只有一个区间包括所要修改区间,还是都包含
    {//都包含
        change(root<<1,l,mid,al,ar,num,k);
        change(root<<1|1,mid+1,r,al,ar,chg,k);//将所要添加的等差数列分裂,chg为计算出来的右区间的首项
        push_up(root);
        return ;
    }
    if(mid>=ar)//所修改的区间只在左区间中
        change(root<<1,l,mid,al,ar,num,k);
    if(mid+1<=al)//只在右区间中
        change(root<<1|1,mid+1,r,al,ar,num,k);
    push_up(root);
    return ;
}
int check(int root,int l,int r,int al,int ar)
{
    if(l>ar||r<al)
        return 0;
    if(l>=al&&r<=ar)
        return t[root].val;
    int mid=(l+r)>>1;
    push_down(root,l,mid,r);
    return  check(root<<1,l,mid,al,ar)+
            check(root<<1|1,mid+1,r,al,ar);//很简单的查询
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&base[i]);
    build(1,1,n);
    int a,b,c,d,e;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&a);
        if(a==1)
        {
            scanf("%d%d%d%d",&b,&c,&d,&e);
            change(1,1,n,b,c,d,e);
        }
        else
        {
            scanf("%d%d",&b,&c);
            printf("%d\n",check(1,1,n,b,c));
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Lance1ot/p/9130588.html