今天某大神跑过来跟我说来学分块吧,很有意思的
于是我就信了= =
对于一个点修改区间查询的数列,把原序列按照sqrt(n)大小为长度分块,每一个块处理它块内的权值和,要查询时,块内的暴力查询,块外直接使用预处理得到的结果sqrt(n)的时间内求出即可
设分块大小为M
如果查询点在一个块的头标记点(i%M),那么将这个点直接前进M步进入下一个块的头标记点即可
如果当前点在一个块内,但并不是头标记点,暴力把答案得出来即可
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn=2333333;
int xl[maxn];
int kuai[maxn];
int n;
void init(){
int y=sqrt(n);
for(int i=0;i<n;i++){
kuai[i/y]+=xl[i];
}
}
void change(int a,int v){
int y=sqrt(n);
xl[a]+=v;
kuai[a/y]+=v;
}
int ask(int a,int b){
int y=sqrt(n);
int ans=0;
while(a<=b){
if(!(a%y)&&a+y<=b){
ans+=kuai[a/y];
a+=y;
}
else{
ans+=xl[a];
a++;
}
}
return ans;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++){
scanf("%d",&xl[i]);
}
init();
//cout<<(int)sqrt(n)<<endl;
int m;
cin>>m;
for(int i=1;i<=m;i++){
int x,a,b;
scanf("%d%d%d",&x,&a,&b);
if(x==1){
change(a-1,b);
}
if(x==2){
if(a>b) swap(a,b);
cout<<ask(a-1,b-1)<<endl;
}
}
return 0;
}