P10516 数据结构 题解
数据结构题解
以下假定
势能线段树。注意到若无二操作,有效一操作至多会进行
二操作单点修改总共只会更新至多
区间和用单点修改线段树的写法即可。
注意要特判
一操作至多进行
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<ctime>
#include<random>
#define int long long
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int N=1e5+10;
int n,m,a[N],b[N];
struct Tree{
#define ls (p<<1)
#define rs (p<<1|1)
#define mid ((l+r)>>1)
int sum[N<<2],minn[N<<2];
inline void pushup(int p){
sum[p]=sum[ls]+sum[rs];
minn[p]=min(minn[ls],minn[rs]);
}
void build(int p,int l,int r){
if(l==r){
sum[p]=a[l]+b[l];
minn[p]=a[l]*b[l];
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
pushup(p);
}
void update(int L,int R,int p,int l,int r,int k,int t){
if(minn[p]>k)return;
if(l==r){
a[l]+=t;
b[l]+=t;
sum[p]=a[l]+b[l];
minn[p]=a[l]*b[l];
return;
}
if(L<=mid)update(L,R,ls,l,mid,k,t);
if(R>mid) update(L,R,rs,mid+1,r,k,t);
pushup(p);
}
void modify(int pos,int p,int l,int r,int x,int y){
if(l==r){
a[pos]=x;
b[pos]=y;
sum[p]=a[l]+b[l];
minn[p]=a[l]*b[l];
return;
}
if(pos<=mid)modify(pos,ls,l,mid,x,y);
if(pos>mid) modify(pos,rs,mid+1,r,x,y);
pushup(p);
}
int query(int L,int R,int p,int l,int r){
if(L<=l&&r<=R)
return sum[p];
int res=0;
if(L<=mid)res+=query(L,R,ls,l,mid);
if(R>mid) res+=query(L,R,rs,mid+1,r);
return res;
}
#undef ls
#undef rs
#undef mid
}T;
signed main()
{
//freopen("020.in","r",stdin);
//freopen("020.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=n;i++)
b[i]=read();
T.build(1,1,n);
while(m--){
int opt=read();
if(opt==1){
int l=read(),r=read(),k=read(),t=read();
if(!t)continue;
T.update(l,r,1,1,n,k,t);
}
if(opt==2){
int pos=read(),x=read(),y=read();
T.modify(pos,1,1,n,x,y);
}
if(opt==3){
int l=read(),r=read();
cout<<T.query(l,r,1,1,n)<<'\n';
}
}
return 0;
}