fjwc2019 D1T1 (dp+树状数组)

Posted kafuuchino

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 

以上是关于fjwc2019 D1T1 (dp+树状数组)的主要内容,如果未能解决你的问题,请参考以下文章

如何在原数组的基础上生成树状数组

JZYZOJ 1360 [usaco2011feb]人品问题 DP 树状数组 离散化

校内训练2019-11-15跳一跳

[BZOJ1264][AHOI2006]基因匹配Match(DP + 树状数组)

奶牛抗议 DP 树状数组

fjwc2019 D2T2 定价 (栈+set+贪心)