luogu 3582 线段树

Posted asdic

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu 3582 线段树相关的知识,希望对你有一定的参考价值。

线段树内存下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
",ans);return 0;
}

 

以上是关于luogu 3582 线段树的主要内容,如果未能解决你的问题,请参考以下文章

luogu3373线段树2..支持区间加值和乘值的线段树

Luogu4556 雨天的尾巴 树上差分线段树合并

Luogu P5280 [ZJOI2019]线段树

线段树模板1 [Luogu P3372]

「Luogu」P3372 线段树模板

LUOGU P3834 模板可持久化线段树 1(主席树)