题解 P1438 【无聊的数列】
daolao们写的题解本juruo表示看不懂....
在这里发个好理解的(我觉得)
其实就是个线段树区间修改加区间查询的模板题 精髓在于维护差分数组b[i] 下面直接上代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long a[1023654],b[1023654];//原始数组a[i]和差分数组b[i];
struct tree{
int l,r;
long long WOW,add;
}t[1000000*4+1];
bool flag;
void build(int p,int l,int r)//建树;
{
t[p].l=l,t[p].r=r;
if(l==r)
{
t[p].WOW=b[l];//用差分数组建树;
return;
}
int mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].WOW=t[p*2].WOW+t[p*2+1].WOW;
}
void spread(int p)//延迟标记;
{
if(t[p].add)
{
t[p*2].WOW+=t[p].add*(t[p*2].r-t[p*2].l+1);
t[p*2+1].WOW+=t[p].add*(t[p*2+1].r-t[p*2+1].l+1);
t[p*2].add+=t[p].add;
t[p*2+1].add+=t[p].add;
t[p].add=0;
}
}
void change(int p,int l,int r,int D)//区间修改的模板;
{
if(t[p].l>=l&&t[p].r<=r)
{
t[p].WOW+=(long long)D*(t[p].r-t[p].l+1);
t[p].add+=D;
return;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(mid>=l) change(p*2,l,r,D);
if(mid<r) change(p*2+1,l,r,D);
t[p].WOW=t[p*2].WOW+t[p*2+1].WOW;
}
int query(int p,int l,int r)//区间查询的模板;
{
if(t[p].l>=l&&t[p].r<=r)
{
return t[p].WOW;
}
long long ans=0;
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(mid>=l) ans+=query(p*2,l,r);
if(mid<r) ans+=query(p*2+1,l,r);
return ans;
}
void Read()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
b[i]=a[i]-a[i-1];//处理差分数组;
}
build(1,1,n);
int t,l,r,k,d;
for(int i=1;i<=m;i++)
{
cin>>t;
if(t==1)
{
cin>>l>>r>>k>>d;
change(1,l,l,k);//单点修改与区间修改
if(r>l) change(1,l+1,r,d);//放在同一个函数中
if(r!=n) change(1,r+1,r+1,-(k+(r-l)*d));
}//利用差分数组性质完成题目要求;
if(t==2)
{
cin>>l;
cout<<query(1,1,l)<<endl;//查询差分数组前缀和以达到
} //求单点值的目的;
}
}
int main(){
Read();//个人习惯
return 0;
}