单纯的模板
区间求和 区间最值 区间加法 点加法
通过区间求和或区间最值 可以求点值
#include
using namespace std;
typedef long long ll;
ll a[100010];
struct T{
ll lt,rt;
ll sum,mx,mn,lazy;
}tr[400010];
void pushup(ll root){//向下传递
ll s1=root<<1,s2=root<<1|1;
tr[root].sum=tr[s1].sum+tr[s2].sum;
tr[root].mx=max(tr[s1].mx,tr[s2].mx);
tr[root].mn=min(tr[s1].mn,tr[s2].mn);
}
void ct(ll g,ll l,ll r){//创建
tr[g].lt=l,tr[g].rt=r;
if(l==r){tr[g].sum=a[l]; tr[g].mx=tr[g].mn=a[l]; return;}
ll mid=(l+r)>>1;
ct(g<<1,l,mid);
ct(g<<1|1,mid+1,r);
pushup(g);
}
void updata(ll g,ll pos,ll val){//将pos位置的值加上val 使用时配合a数组,记得更新a数组的值
if(tr[g].lt==tr[g].rt&&tr[g].lt==pos)
{tr[g].sum+=val; tr[g].mx+=val; tr[g].mn+=val; return;}
ll mid=(tr[g].lt+tr[g].rt)>>1;
if(pos<=mid) updata(g<<1,pos,val);
else updata(g<<1|1,pos,val);
pushup(g);
}
ll qmx(ll g,ll x,ll y){//qmx[1,x,y] 取[x,y]的最大值
if(tr[g].lt==x&&tr[g].rt==y) return tr[g].mx;
ll mid=(tr[g].lt+tr[g].rt)>>1;
if(y<=mid) return qmx(g<<1,x,y);
else if(x>mid) return qmx(g<<1|1,x,y);
else {ll a=qmx(g<<1,x,mid);ll b=qmx(g<<1|1,mid+1,y);return max(a,b);}
}
ll qmn(ll g,ll x,ll y){//qmn[1,x,y] 取[x,y]的最小值
if(tr[g].lt==x&&tr[g].rt==y) return tr[g].mn;
ll mid=(tr[g].lt+tr[g].rt)>>1;
if(y<=mid) return qmn(g<<1,x,y);
else if(x>mid) return qmn(g<<1|1,x,y);
else{ll a=qmn(g<<1,x,mid);ll b=qmn(g<<1|1,mid+1,y);return min(a,b);}
}
void change(ll h,ll l,ll r,ll s,ll e,ll k){
if(l==s&&r==e){tr[h].lazy+=k; return;}
tr[h].sum+=(e-s+1)*k;
ll mid=(l+r)/2;
if(s>=mid+1) change(h*2+1,mid+1,r,s,e,k);
else if(e<=mid) change(h*2,l,mid,s,e,k);
else {change(h*2,l,mid,s,mid,k);change(h*2+1,mid+1,r,mid+1,e,k);}
}
ll qsum(ll g,ll x,ll y){//qsum[1,x,y] 取[x,y]的和
if(tr[g].lt==x&&tr[g].rt==y) return tr[g].sum+tr[g].lazy*(tr[g].rt-tr[g].lt+1);
ll mid=(tr[g].lt+tr[g].rt)>>1;
ll ret=0;
if(tr[g].lazy){
tr[g].sum+=tr[g].lazy*(tr[g].rt-tr[g].lt+1);
change(g*2,tr[g].lt,mid,tr[g].lt,mid,tr[g].lazy);
change(g*2+1,mid+1,tr[g].rt,mid+1,tr[g].rt,tr[g].lazy);
tr[g].lazy=0;
}
if(y<=mid)return qsum(g<<1,x,y);
else if(x>mid)return qsum(g<<1|1,x,y);
else{ret+=qsum(g<<1,x,mid); ret+=qsum(g<<1|1,mid+1,y); return ret;}
}
void qjup(int root, int nstart, int nend, int ustart, int uend, int addVal)
{//qjup(1,1,n,x,y,k) [x,y]区间内的数均加k
if(ustart > nend || uend < nstart) return ;
if(ustart <= nstart && uend >= nend)
{
tr[root].sum += addVal;
tr[root].mn += addVal;
tr[root].mx += addVal;
return ;
}
pushup(root);
int mid = (nstart + nend) / 2;
qjup(root*2, nstart, mid, ustart, uend, addVal);
qjup(root*2+1, mid+1, nend, ustart, uend, addVal);
tr[root].mn = min(tr[root*2].mn , tr[root*2+1].mn);
tr[root].mx = max(tr[root*2].mx, tr[root*2+1].mx);
tr[root].sum = tr[root*2].sum + tr[root*2+1].sum;
}
int main(){
ll m,n;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];//初始化a数组
ct(1,1,n);
while(m--)
{//各种命令
ll p,x,y,k;
cin>>p>>x>>y;
if(p==1) y
{
// updata(1,x,y-a[x]);//updata 更新x位置+
// qjup(1,1,n,x,x,y-a[x]);//
a[x]=y;//及时更新a数组
}
else if(p==2) cout<