传送门
题解:
对公差分块,小的直接建立线段树,大的暴力查。
但是由于两部分的常数差异,实际上公差阈值设成10就差不多了
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;T num;bool f=false;
while(!isdigit(c=gc()))f=c=='-';num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return f?-num:num;
}
inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int N=7e4+7,S=10,NINF=-0x3f3f3f3f;
int n,m;
int a[N],M;
struct data{
int mx[N<<2];
int st[N],ed[N],pos[N];
void init(int d){
int p=0;
for(int re i=1;i<=d;++i){
for(int re j=i;j<=n;j+=d)
pos[st[j]=++p]=j;
for(int re j=i;j<=n;j+=d)ed[j]=p;
}
build();
}
void build(){
for(int re i=M+1;i<=M+n;++i)mx[i]=a[pos[i-M]];
mx[M]=NINF;for(int re i=M+n+1;i<M+M;++i)mx[i]=NINF;
for(int re i=M-1;i;--i)mx[i]=std::max(mx[i<<1],mx[i<<1|1]);
}
void modify(int p,int v){
for(mx[p+=M]=v,p>>=1;p;p>>=1)mx[p]=std::max(mx[p<<1],mx[p<<1|1]);
}
int query(int l,int r){
int ans=NINF;
for(l+=M-1,r+=M+1;l^r^1;l>>=1,r>>=1){
if(l&1^1)ans=std::max(ans,mx[l^1]);
if(r&1) ans=std::max(ans,mx[r^1]);
}
return ans;
}
void update(int u,int v){modify(st[u],v);}
int query(int u){return query(st[u],ed[u]);}
}t[S+1];
signed main(){
#ifdef zxyoi
freopen("karin.in","r",stdin);
#endif
n=gi();
for(M=1;M<=n+1;M<<=1);
for(int re i=1;i<=n;++i)a[i]=gi();
for(int re i=1;i<=S;++i)t[i].init(i);
m=gi();
while(m--){
switch(gi()){
case 0:{
int p=gi(),v=gi();a[p]+=v;
for(int re i=1;i<=S;++i)t[i].update(p,a[p]);
break;
}
case 1:{
int st=gi(),d=gi();
if(d>S){
int ans=NINF;
for(;st<=n;st+=d)ans=std::max(ans,a[st]);
cout<<ans<<"\n";
}else cout<<t[d].query(st)<<"\n";
break;
}
}
}
return 0;
}