线段树内存下mx[k]的值是动态的1-i这个区间的贡献答案
实际上点存的就是区间答案,但用max是为了求最大区间答案(有可能虽然贡献被消除但后来有更大的贡献填补答案空缺)
#include<bits/stdc++.h> #define rep(i,x,y) for(register int i=x;i<=y;i++) #define dec(i,x,y) for(register int i=x;i>=y;i--) #define LL long long #define In freopen("7.in","r",stdin) #define In2 freopen("8.in","r",stdin) using namespace std; const int N=1e6+50; inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;} int n,m,w[N],f[N],mark[N],pre[N]; LL mx[N<<2],tag[N<<2],ans=0; inline void pushup(int k){ mx[k]=max(mx[k<<1],mx[k<<1|1]);} inline void pushdown(int k,int l,int r,int mid){ if(l==r) return; LL v=tag[k];tag[k]=0; tag[k<<1]+=v;mx[k<<1]+=v; tag[k<<1|1]+=v;mx[k<<1|1]+=v;} inline void change(int k,int l,int r,int x,int y,LL d){ if(x<=l&&r<=y){ tag[k]+=d;mx[k]+=d;return;} int mid=(l+r)>>1; if(tag[k]) pushdown(k,l,r,mid); if(x<=mid) change(k<<1,l,mid,x,y,d); if(mid<y) change(k<<1|1,mid+1,r,x,y,d); pushup(k); } inline LL query(int k,int l,int r,int x,int y){ if(x<=l&&r<=y) return mx[k];LL res=0; int mid=(l+r)>>1;if(tag[k])pushdown(k,l,r,mid); if(x<=mid) res=max(res,query(k<<1,l,mid,x,y)); if(mid<y) res=max(res,query(k<<1|1,mid+1,r,x,y)); return mx[k];} int main(){ n=read();m=read(); rep(i,1,n) f[i]=read(); rep(i,1,m) w[i]=read(); rep(i,1,n) pre[i]=mark[f[i]],mark[f[i]]=i; rep(i,1,n){ change(1,1,n,pre[i]+1,i,w[f[i]]); if(pre[i]) change(1,1,n,pre[pre[i]]+1,pre[i],-w[f[i]]); ans=max(ans,query(1,1,n,1,i)); } printf("%lld\n",ans);return 0; }
原文地址:https://www.cnblogs.com/asdic/p/9726990.html
时间: 2024-10-11 08:12:50