思路分析:
等差数列用线段树是可以维护的,但是当前我们用分块很明显可以很好地维护等差数列的特性。
操作分为三类:
准备:对每个块准备begins与mid数组(注意不能使用begin作为变量名或者数组名,因为编译不通过)
1,修改:按照普通分块修改,begins记录这一块的起始位置K,mid记录这一块的公差
void modify(int l,int r,int K,int D){
int L = l,R = r;
ll maxVal = (R-L)*D+K;
while(l%model!=0&&l<=r){
a[l]+=K+(l-L)*D*1ll;
l++;
}
while((r+1)%model!=0&&r>=l){//这一点一定要记住,r+1!!!!
a[r]+=maxVal-(R-r)*D;
r--;
}
while(l<=r){
begins[l/model]+=K+(l-L)*D*1ll;
mid[l/model]+=D;
l+=model;
}
}
2,pushdown操作,这一点为了维护查询的数据正确
void pushdown(int p){
ll val1 = begins[p],val2 = mid[p];
for(int i=lb[p];i<=rb[p];i++){
a[i]+=val1;
val1+=val2;
}
begins[p]=0;mid[p]=0;
}
3,查询操作,这就不多说了,主要是pushdown
void query(int x){
pushdown(x/model);
printf("%lld\n",a[x]);
}
下面就是总的代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
//常数3*3千万都能100ms过,大概4亿内都能过
const int maxn = 100005;
const int model = 317;
ll n,m,a[maxn],sum[maxn],size[maxn],begins[model+5],mid[model+5];
vector<ll>G[model+5];
ll lb[maxn],rb[maxn],cnt;
void modify(int l,int r,int K,int D);
void query(int x);
//分块是个非常好的做法,N根号N现在这个算法非常强 ,可以卡过许多东西
void init(){
scanf("%lld %lld",&n,&m);
lb[0]=0;rb[0]=model-1;
for(int i=1;i<=model-1;i++){
lb[i] = rb[i-1]+1;
rb[i] = lb[i]+model-1;
}
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
G[i/model].push_back(a[i]);
}
for(int i=0;i<=n/model;i++){
size[i] = G[i].size();
}
/*for(int i=0;i<=n/model;i++){
printf("%d\n",size[i]);
}*/
}
void work(){
int opt;
int l,r,K,D;
for(int i=1;i<=m;i++){
scanf("%d",&opt);
if(opt==1){
scanf("%d %d %d %d",&l,&r,&K,&D);
modify(l-1,r-1,K,D);
// printf("1\n");
}
if(opt==2){
scanf("%d",&l);
query(l-1);
}
}
}
void pushdown(int p){
ll val1 = begins[p],val2 = mid[p];
for(int i=lb[p];i<=rb[p];i++){
a[i]+=val1;
val1+=val2;
}
begins[p]=0;mid[p]=0;
}
void query(int x){
pushdown(x/model);
printf("%lld\n",a[x]);
}
void modify(int l,int r,int K,int D){
int L = l,R = r;
ll maxVal = (R-L)*D+K;
while(l%model!=0&&l<=r){
a[l]+=K+(l-L)*D*1ll;
l++;
}
while((r+1)%model!=0&&r>=l){//这一点一定要记住,r+1!!!!
a[r]+=maxVal-(R-r)*D;
r--;
}
while(l<=r){
begins[l/model]+=K+(l-L)*D*1ll;
mid[l/model]+=D;
l+=model;
}
}
int main(){
//freopen("seq.in","r",stdin);
//freopen("seq.out","w",stdout);
init();
work();
return 0;
}
好啦,感谢观看!