zoukankan      html  css  js  c++  java
  • BZOJ 3747 POI2015 Kinoman

    因为上午没有准备够题目,结果发现写完这道题没题可写了QAQ

    又因为这道题范围是100w,我写了发线段树,以为要T,上午就花了一个小时拼命卡常数

    结果下午一交居然过了QAQ

    我们考虑枚举L,求最大R使得[L,R]是对于当前L最大权值的区间

    考虑每个点的影响

    如果从L向右他是第一个,那么他会对后面产生a[f[L]]的贡献

    如果从L向右他是第二个,那么他会对后面产生-a[f[L]]的贡献

    然后我们维护一棵线段树,每次查询最值并且进行更新即可

    include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    using namespace std;
     
    typedef long long LL;
    const int maxn=1000010;
    int n,m,x,y,v,tim;
    int f[maxn];
    int a[maxn];
    int next[maxn],h[maxn];
    LL mx[maxn<<2],add[maxn<<2];
    LL ans=0,tot=0;
     
    inline void read(int &num){
        num=0;char ch=getchar();
        while(ch<'!')ch=getchar();
        while(ch>='0'&&ch<='9')num=(num<<3)+(num<<1)+ch-'0',ch=getchar();
    }
    inline LL Max(LL a,LL b){return a>b?a:b;}
    inline void push_down(int o){
        int L=(o<<1),R=(L|1);
        add[L]+=add[o];mx[L]+=add[o];
        add[R]+=add[o];mx[R]+=add[o];
        add[o]=0;
    }
    inline void modify(int o,int L,int R){
        if(L>=x&&R<=y){
            mx[o]+=v;add[o]+=v;
            return;
        }
        if(add[o]!=0)push_down(o);
        int mid=(L+R)>>1;
        if(y<=mid)modify(o<<1,L,mid);
        else if(x>mid)modify(o<<1|1,mid+1,R);
        else modify(o<<1,L,mid),modify(o<<1|1,mid+1,R);
        mx[o]=Max(mx[o<<1],mx[o<<1|1]);
    }
    inline LL ask(int o,int L,int R){
        if(L>=x&&R<=y)return mx[o];
        if(add[o]!=0)push_down(o);
        int mid=(L+R)>>1;
        if(y<=mid)return ask(o<<1,L,mid);
        else if(x>mid)return ask(o<<1|1,mid+1,R);
        else return Max(ask(o<<1,L,mid),ask(o<<1|1,mid+1,R));
    }
    int main(){
        read(n);read(m);y=n;
        for(int i=1;i<=n;++i)read(f[i]);
        for(int i=1;i<=m;++i)read(a[i]);
        for(int i=n;i>=1;--i){
            next[i]=h[f[i]];
            h[f[i]]=i;
        }
        for(int i=1;i<=m;++i){
            if(h[i]){
                x=h[i];v=a[i];
                modify(1,1,n);
                if(next[h[i]]){
                    x=next[h[i]];v=-a[i];
                    modify(1,1,n);
                }
            }
        }
        for(int L=1;L<=n;++L){
            x=L;
            ans=Max(ans,ask(1,1,n)-tot);
            tot+=a[f[L]];
            int n1=next[L],n2=next[n1];
            if(n1){
                x=n1;v=(a[f[L]]<<1);
                modify(1,1,n);
            }
            if(n2){
                x=n2;v=-a[f[L]];
                modify(1,1,n);
            }
        }printf("%lld
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    进度条4
    构建之法读书笔记02
    进度条3
    个人作业四则运算2测试
    个人作业3
    从小工到专家阅读笔记01
    个人冲刺07
    个人冲刺06
    个人冲刺05
    学习进度条08
  • 原文地址:https://www.cnblogs.com/joyouth/p/5371881.html
Copyright © 2011-2022 走看看