zoukankan      html  css  js  c++  java
  • CF573E Bear and Bowling

    Link
    我们设(f_{i,j})表示前(i)个数中选(j)个的最大值。
    那么显然有(f_{i,j}=max(f_{i-1,j},f_{i-1,j-1}+j*a_i))
    这个东西我们首先可以把它的第一维给滚掉。
    然后我们知道这是个(O(n^2))的东西,所以要考虑优化。
    有一个结论是(forall iin[1,n],exist kin[1,i],s.t.forall jin[0,k),f_{i,j}=f_{i-1,j},forall jin[k,i],f_{i,j}=f_{i-1,j-1}+j*a_i)
    这个东西感性理解一下吧,就是你前面选的越多,选(a_i)时可能产生的贡献就越大。
    具体证明上洛谷题解里面找吧。
    那么我们每次可以把(k)二分出来,然后就相当于在原序列的(f_{k-1},f_k)之间再插一个(f_k)进去,后面的(f_j)加上一个等差数列(a_i*j)
    这个东西可以用平衡树来做。

    #include<bits/stdc++.h>
    #define lc ch[p][0]
    #define rc ch[p][1]
    #define ll long long
    using namespace std;
    int read(){int x;scanf("%d",&x);return x;}
    ll max(ll a,ll b){return a>b? a:b;}
    const int N=100007;
    int fa[N],ch[N][2],s[N],n,root,cnt;ll A[N],B[N],val[N];
    int isr(int x){return ch[fa[x]][1]==x;}
    void pushup(int p){s[p]=s[lc]+s[rc]+1;}
    void modify(int p,ll a,ll b){val[p]+=a*(s[lc]+1)+b,A[p]+=a,B[p]+=b;}
    void pushdown(int p){ if(A[p]||B[p]) { if(lc) modify(lc,A[p],B[p]); if(rc) modify(rc,A[p],B[p]+A[p]*(s[lc]+1)); A[p]=B[p]=0; } }
    void pushall(int x){if(fa[x])pushall(fa[x]);pushdown(x);}
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],k=isr(x);if(z)ch[z][isr(y)]=x;
        fa[x]=z,fa[y]=x,fa[ch[x][!k]]=y,ch[y][k]=ch[x][!k],ch[x][!k]=y,pushup(y);
    }
    void splay(int x)
    {
        pushall(x);
        for(;fa[x];rotate(x)) if(fa[fa[x]]) rotate((isr(x)^isr(fa[x]))? x:fa[x]);
        pushup(root=x);
    }
    ll Kth(int k)
    {
        int p=root;
        while(1)
    	if(k>s[lc]+1) k-=s[lc]+1,p=rc;
    	else if(s[lc]>=k) p=lc;
    	else return splay(p),val[p];
    }
    ll query(int p)
    {
        if(!p) return -1e18;
        pushdown(p);
        return max(val[p],max(query(lc),query(rc)));
    }
    int main()
    {
        n=read(),s[1]=root=cnt=1;int i,x,l,r,mid,ans;
        for(i=1;i<=n;++i)
        {
    	x=read(),l=0,r=i-2,ans=i-1;
    	while(l<=r){mid=l+r>>1;if(Kth(mid+1)+(mid+1ll)*x>Kth(mid+2))ans=mid,r=mid-1;else l=mid+1;}
            Kth(ans+1),fa[++cnt]=root,fa[ch[root][1]]=cnt,ch[cnt][1]=ch[root][1],ch[root][1]=cnt,val[cnt]=val[root],modify(cnt,x,1ll*x*ans);
        }
        return !printf("%lld",query(root));
    }
    
  • 相关阅读:
    使用element-ui是下拉筛选选择
    vue 组件传值
    vue element 地址联动的使用
    vux scroller
    实时监听组件中路由的变化
    vuex的使用
    对移动端滚动高度的获取
    【转】ACM 取石子问题
    【转】ACM博弈知识汇总
    EOJ 2857 编辑距离
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11617785.html
Copyright © 2011-2022 走看看