势能线段树|
拉线段树题单时发现的这道
花神游历各国的骚操作至今让我印象深刻,原来有名字
所谓势能,大意就是原本你在高空,操作一点下降一点,势能变少一点..当你落地时,修改就没意义了
因此可以打一个落地标记:)
适用在操作次数不会很多、lazytag失效时,常见的比如开根号,区间取mod,位运算。
对于此题,当区间最大值<x时就不用修改了,维护一下最大值。
修改次数的证明不会,感性理解一下取mod下降速度也很快。
#include<bits/stdc++.h> #define ls (rt<<1) #define rs (rt<<1|1) #define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0) using namespace std; typedef long long ll; const int maxn=1e5+5; int a[maxn]; struct seg{ int l,r,mx; ll sum; }t[maxn<<2]; void push_up(int rt){ t[rt].mx=max(t[ls].mx,t[rs].mx); t[rt].sum=t[ls].sum+t[rs].sum; } void build(int rt,int l,int r){ t[rt].l=l;t[rt].r=r; if(l==r){ t[rt].mx=a[l]; t[rt].sum=1ll*a[l]; return; } int mid=(l+r)>>1; build(ls,l,mid);build(rs,mid+1,r); push_up(rt); } void update(int rt,int l,int r,int x){ if(l<=t[rt].l&&t[rt].r<=r){ // update if(t[rt].mx<x) return; } if(t[rt].l==t[rt].r){ t[rt].mx%=x; t[rt].sum=1ll*t[rt].mx; return; } if(t[ls].r>=l) update(ls,l,r,x); if(t[rs].l<=r) update(rs,l,r,x); push_up(rt); } void modify(int rt,int l,int r,int x){ if(l<=t[rt].l&&t[rt].r<=r){ // update t[rt].mx=x; t[rt].sum=x; return; } if(t[ls].r>=l) modify(ls,l,r,x); if(t[rs].l<=r) modify(rs,l,r,x); push_up(rt); } ll ask(int rt,int l,int r){ if(l<=t[rt].l&&t[rt].r<=r){ return t[rt].sum;// } ll ans=0; if(t[ls].r>=l) ans+=ask(ls,l,r);// if(t[rs].l<=r) ans+=ask(rs,l,r);// return ans; } int n,m; int main(){ //freopen("lys.in","r",stdin); fastio; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; build(1,1,n); for(int i=1;i<=m;i++){ int op; cin>>op; if(op==1){ int l,r;cin>>l>>r; cout<<ask(1,l,r)<<endl; } else if(op==2){ int l,r,x;cin>>l>>r>>x; update(1,l,r,x);//对x取模 } else { int k,x;cin>>k>>x; modify(1,k,k,x); } } }
标签:rt,势能,Sequence,int,线段,rs,Codeforces,ls,Child From: https://www.cnblogs.com/liyishui2003/p/17169571.html