zoukankan      html  css  js  c++  java
  • fjwc2019 D1T1 全连(dp+树状数组)

    #178. 「2019冬令营提高组」全连

    显然我们可以得出一个$O(n^2)$的dp方程

    记$f(i)$为取到第$i$个音符时的最大分数,枚举下一个音符的位置$j$进行转移。

    蓝后我们就可以用树状数组存下$f(i)$的最大值,每次用$logn$的复杂度每次询问$j=1 ightarrow i-t[i]$中最大$f(j)$值。

    酱紫复杂度就变成了$O(nlogn)$

    对于$f(i)$在位置$i+t[i]$之后才能作为转移的一个选择的问题,我们可以打一个延迟标记(ping函数),用类似链式前向星的结构存储(就像存边一样)。

    每次到达一个$k$,就把每个从$k$开始起转移作用的$f(i)加入树状数组。

    #include<cstdio>
    typedef long long ll;
    ll max(ll a,ll b){return a>b?a:b;}
    void read(ll &x){
        char c=getchar();x=0;
        while(c<'0'||c>'9') c=getchar();
        while('0'<=c&&c<='9') x=x*10+(c^48),c=getchar();
    }
    #define N 1000005
    ll s[N],a[N],t[N],f[N],ans;
    int n,cnt,hd[N],nxt[N],ed[N],poi[N];
    void add(int x,ll v){for(;x<=n;x+=x&-x)s[x]=max(s[x],v);}
    ll ask(int x){ll re=0;for(;x;x-=x&-x)re=max(re,s[x]);return re;}
    void ping(int x,int y){
        nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt;
        ed[x]=cnt; poi[cnt]=y;
    }
    int main(){
        freopen("fc.in","r",stdin);
        freopen("fc.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;++i) read(t[i]);
        for(int i=1;i<=n;++i) read(a[i]);
        for(int i=1;i<=n;++i){
            for(int j=hd[i];j;j=nxt[j]) add(poi[j],f[poi[j]]);//f[poi[j]]从i开始可以作为一个选择,加入树状数组
            f[i]=a[i]*t[i];
            if(i>t[i]) f[i]+=ask(i-t[i]);//查询1~i-t[i]的最优选择
            if(i+t[i]<=n) ping(i+t[i],i);//把f(i)加入位置i+t[i]的标记中
            ans=max(ans,f[i]);
        }printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    tp框架自带扩展分页类修改样式
    win7获取管理员权限
    Git学习手记(二)
    安卓导出安装包
    浅谈存储过程
    Java宝典
    单例设计模式
    关于Cookie的有关内容
    开辟html5和css3学习随笔(2015-3-2)
    关于面试题
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10426896.html
Copyright © 2011-2022 走看看