题解 P1438 无聊的数列
这道题似乎有许多种做法,如利用等差数列上加上一个等差数列仍然是一个等差数列的性质,或把
我是对原数组的差分数组再次差分。
等差数列的两项之差为
设原数组
对
询问序列的第
仔细一想
设
用数组
用树状数组维护
时间复杂度为
不知为何跑起来飞快
截止2019.6.29日,这份代码在你谷排第四
#include<iostream>
#include<cctype>
#include<cstdio>
const int MAXN=100001;int n;
#define LL long long
LL as[MAXN+10],_c0[MAXN+10],_c1[MAXN+10],_c2[MAXN+10];
LL read(){
LL sum=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')sum=sum*10+ch-'0',ch=getchar();
return f*sum;
}
inline void add0(const int &x,const LL &k){
int i;for (i=x;i<=n;i+=i&(-i)) _c0[i]+=k;
}
inline LL ask0(const int &x){
LL ans=0;int i;
for (i=x;i;i-=i&(-i)) ans+=_c0[i];return ans;
}
inline void add1(const int &x,const LL &k){
int i;for (i=x;i<=n;i+=i&(-i)) _c1[i]+=k;
}
inline LL ask1(const int &x){
LL ans=0;int i;
for (i=x;i;i-=i&(-i)) ans+=_c1[i];return ans;
}
int main(){
int m,i;
n=read();m=read();
for (i=1;i<=n;++i) as[i]=as[i-1]+read();
int op,l,r;
LL k,d,c0,c1,c2,ad1,ad2;
for (i=1;i<=m;++i){
op=read();
if (op==1){
l=read(),r=read(),k=read(),d=read();
ad1=-k-(r-l+1)*d,ad2=k+(r-l)*d;
add0(l,k),add0(r+1,ad1),add0(l+1,d-k),add0(r+2,ad2);
add1(l,l*k),add1(r+1,(r+1)*ad1);
add1(l+1,(l+1)*(d-k)),add1(r+2,(r+2)*ad2);
}
else {
l=read();
c1=ask1(l),c0=ask0(l);
printf("%d\n",as[l]-as[l-1]+(l+1)*c0-c1);
}
}
}