题面

luogu P1438 无聊的数列

分析

等差数列!等差数列!等差数列!
等差!等差!等差!
差分!差分!差分!
就这样喽

luogu P1438 无聊的数列

假设有一数列a1,a2,a3,a4…a10,对其加上等差数列t,t+d,t+2d…t+6d,(L=2,R=8)
将其构造成差分数组,如中间部分所示,很明显可以看到差分数组的绿色部分只需要全部加上d,第L项加上t,第R+1项加上
tRL×d(-t-(R-L)\times d)就可以维护好整个差分数组且满足差分数组的前缀和性质了
于是本题其实就是用线段树去维护差分数组的区间和

code

#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(int i=start;i<=end;i++)
#define clean(arry,num); memset(arry,num,sizeof(arry));
int n,m;
const int maxn=100000+10;
const int maxm=100000+10;
int d[maxn];
int sum[maxn<<2];
int lazy[maxn<<2];
inline int read()
{
    int ans=0;bool neg=false;char r=getchar();
    while(r>'9'||r<'0'){if(r=='-')neg=true;r=getchar();}
    while(r>='0'&&r<='9'){ans=ans*10+r-'0';r=getchar();}
    return (neg)?-ans:ans;
}
void pushup(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,int len)
{
    if(!lazy[rt])return;
    lazy[rt<<1]+=lazy[rt];
    lazy[rt<<1|1]+=lazy[rt];
    sum[rt<<1]+=lazy[rt]*(len-((len)>>1));//优先级问题!不能写len-len>>1
    sum[rt<<1|1]+=lazy[rt]*((len)>>1);
    lazy[rt]=0;
}
void buildtree(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=d[l];
        return;
    }
    int m=(l+r)>>1;
    buildtree(l,m,rt<<1);
    buildtree(m+1,r,rt<<1|1);
    pushup(rt);
}
int query(int ql,int qr,int nl,int nr,int rt)
{
    if(ql<=nr&&nr<=qr)return sum[rt];
    pushdown(rt,nr-nl+1);
    int m=(nl+nr)/2;
    int ans=0;
    if(m>=ql)ans+=query(ql,qr,nl,m,rt<<1);
    if(qr>m)ans+=query(ql,qr,m+1,nr,rt<<1|1); 
    return ans;
}
void update(int ul,int ur,int nl,int nr,int num,int rt)
{
    if(ul<=nl&&nr<=ur)
    {
        lazy[rt]+=num;
        sum[rt]+=(nr-nl+1)*num;
        return;
    }
    pushdown(rt,nr-nl+1);
    int m=(nl+nr)/2;
    if(ul<=m)update(ul,ur,nl,m,num,rt<<1);
    if(m<ur)update(ul,ur,m+1,nr,num,rt<<1|1);
    pushup(rt);
}
int main()
{
    n=read();m=read();
    int numfront=0;
    loop(i,1,n)
    {
        int aa=read();
        d[i]=aa-numfront;
        numfront=aa;
    }
    buildtree(1,n,1);
    loop(i,1,m)
    {
        int op=read();
        if(op==2)
        {
            int r=read(); 
            printf("%d\n",query(1,r,1,n,1));
        }
        else if(op==1)
        {
            int l,r,k,d;l=read();r=read();k=read();d=read();
            update(l,l,1,n,k,1);
            if(l!=r)update(l+1,r,1,n,d,1);//小心越界!!!l+1不能大于r,r+1不能大于n!!!!
            if(r!=n)update(r+1,r+1,1,n,-k-(r-l)*d,1);
        }
    }
    return 0;
} 

学到的东西

都在代码里了~~~~

相关文章: