• DP优化 G Divide a Sequence


    G - Divide a Sequence

    前几天打的ABC,到最后两道还是不会,摆烂....以为是数学题,没想到是DP优化的题目...还是对数学题的恐惧太深了...
    image
    朴素的DP也是比较好好设的,考虑怎么优化,既然宏观上看不出来,我们不妨将其每一项都拆开,运用微积分的思想,没劝退,只是吓唬一下你。就是这样:
    image
    可以发现,如果我们能解决前一半的max的问题,后一半减去min的一部分是类似的。
    考虑前面怎么做,可以发现其实就是前面的每一部分的范围都扩大进了a[i],让a[i]和他们取max,让我们想想哪个数据结构是符合这个?单调栈,我们维护一个从栈顶到栈低依次递增的栈,每个栈中元素额外维护一个它的f[]的和。当一个元素要被从栈中弹出时,它所维护的f[]值累加到把它弹出的元素即可。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=3e5+10,P=998244353;
    int n,a[N],top1,st1[N],top2,st2[N];
    ll f[N],b1[N],b2[N],ans1,ans2;   
    int main()
    {   
    //    freopen("1.in","r",stdin);
        scanf("%d",&n);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        f[0]=1;
        ans1=a[1];ans2=a[1];
        st1[++top1]=1;st2[++top2]=1;
        b1[1]=f[0];b2[1]=f[0];
        for(int i=2;i<=n;++i)
        {
            while(top1&&a[i]>=a[st1[top1]]) 
            {
                b1[i]=(b1[i]+b1[st1[top1]])%P; 
                ans1=((ans1-b1[st1[top1]]*a[st1[top1]]%P)%P+P)%P;
                --top1;
            }
            st1[++top1]=i;
            b1[i]+=f[i-1];
            ans1=(ans1+b1[i]*a[i]%P)%P;
            while(top2&&a[i]<=a[st2[top2]])
            {
                b2[i]=(b2[i]+b2[st2[top2]])%P;
                ans2=((ans2-b2[st2[top2]]*a[st2[top2]]%P)%P+P)%P;
                --top2;
            }
            st2[++top2]=i;
            b2[i]+=f[i-1];
            ans2=(ans2+b2[i]*a[i]%P)%P;
            f[i]=((ans1-ans2)%P+P)%P;
        }
        printf("%lld",f[n]);
        return 0;
    }
    
  • 相关阅读:
    hdu 2680 最短路径(dijkstra算法+多源最短路径单源化求最小值)
    kmp算法
    STP根交换机,指定端口,根端口,阻塞端口
    python,django安装
    交换机access与trunk口
    树状数组
    hdoj 2191(多重背包)
    hdoj 2601(判断N=i*j+i+j)
    二维背包经典问题
    hdoj 2602(背包)
  • 原文地址:https://www.cnblogs.com/gcfer/p/15785847.html
Copyright © 2020-2023  润新知