zoukankan      html  css  js  c++  java
  • *游戏

    bzoj十一月月赛

    有n轮游戏,第i轮游戏有权值w[i](可正可负),如果选择玩第i次游戏,并且这是第k次玩这个游戏,那么会获得$w_i(k^2+ak+b)$点分数。

    你需要输出恰好玩1…n轮游戏最多能获得多少分。n<=1e5,a^2>=4b。

    首先a^2>=4b显然只是在告诉我们k^2+ak+b非负,因为如果有负的负负得正就很尴尬了。 a^2>=4b好像没啥用

    然后我们可以发现最优解是可以通过增量法构造的,就是说对于k个元素的最优解,存在一种k+1个元素的最优解比这个最优解多一个元素。证明大约如下:

    image

    那么我们可以考虑从k=0开始每次选择一个元素加进去,作为k+1的方案。

    假设加完了,那我们把每次加的元素排成一排,设f[k]表示选k个元素的方案价值,g[k]=f[k]-f[k-1],那么g应该单调不上升(由于答案是凸的)。那么我们考虑对于一个新的元素,啥时候应该把它加进去,我们发现我们可以直接追踪这个g,二分到一个位置使得g单调不上升。

    考虑这个元素加进去之后会有什么影响。容易发现一个元素插到某个位置之后,前面的g显然没有影响,对于后面的g,这个元素企图篡权夺位失败,每次失败都要后移一位。

    那么对于一个后面的g,假设它原来的rank为r,g'=g+(v[r+1]-v[r])*刚插入的w=g+(2r+a+1)*刚插入的w,r'=r+1。splay上打标记维护即可。打标记的时候需要格外小心,因为多个标记合并的时候rank改变是有先后顺序的,详见代码吧。

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
    #define SZ 666666
    int an=0,ch[SZ][2],fa[SZ],sz[SZ],root,rk[SZ];
    ll g[SZ],dgr[SZ],dg[SZ]; int dr[SZ];
    void sett(int x,int r,ll gr,ll gg)
    {
        if(!x) return;
        g[x]+=gr*rk[x]+gg; rk[x]+=r;
        dgr[x]+=gr; dg[x]+=gg+gr*dr[x]; dr[x]+=r;
    }
    inline void pd(int x)
    {
        sett(ch[x][0],dr[x],dgr[x],dg[x]);
        sett(ch[x][1],dr[x],dgr[x],dg[x]);
        dr[x]=dgr[x]=dg[x]=0;
    }
    void upd(int x)
    {if(!x) return; sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;}
    void rot(int x)
    {
        if(!fa[x]) return;
        int y=fa[x],f=fa[y],p=ch[y][1]!=x;
        fa[x]=f; fa[y]=x;
        if(f) ch[f][ch[f][1]==y]=x;
        int g=ch[x][p];
        ch[x][p]=y; ch[y][!p]=g;
        if(g) fa[g]=y;
        upd(y); upd(x); upd(f);
    }
    int ss[SZ],sn=0;
    void splay(int x,int f=0)
    {
        for(int y=x;y!=f;y=fa[y]) ss[++sn]=y;
        while(sn) pd(ss[sn--]);
        while(fa[x]!=f)
        {
            int y=fa[x];
            if(fa[y]!=f)
                (ch[fa[y]][1]==y^ch[y][1]==x)
                ?rot(x):rot(y); rot(x);
        }
        if(!f) root=x;
    }
    int n,a,b,w[SZ]; ll v[SZ];
    void ins(int x,int p,int a)
    {
        while(1)
        {
            ++sz[x]; pd(x);
            int r=(g[x]>=v[rk[x]]*ll(a));
            if(!ch[x][r])
            {ch[x][r]=p; sz[p]=1; fa[p]=x; return;}
            x=ch[x][r];
        }
    }
    ll ans[SZ];
    void dfs(int x)
    {
        if(!x) return;
        pd(x); ans[rk[x]]=g[x];
        dfs(ch[x][0]); dfs(ch[x][1]);
    }
    int main()
    {
        scanf("%d%d%d",&n,&a,&b);
        for(int i=1;i<=n;++i)
            scanf("%d",w+i),
            v[i]=(i+a)*(ll)i+b;
        sz[1]=rk[1]=root=1; g[1]=w[1]*v[1];
        for(int i=2;i<=n;++i)
        {
            ins(root,i,w[i]); splay(i);
            rk[i]=sz[ch[i][0]]+1;
            g[i]=(ll)v[rk[i]]*w[i];
            sett(ch[i][1],1,w[i]*2,(a+1)*ll(w[i]));
        }
        dfs(root);
        for(int i=2;i<=n;++i) ans[i]+=ans[i-1];
        for(int i=1;i<=n;++i)
            printf("%lld
    ",ans[i]);
    }
  • 相关阅读:
    1.4.2.3. SETUP(Core Data 应用程序实践指南)
    1.4.2.2. PATHS(Core Data 应用程序实践指南)
    1.4.2.1. FILES(Core Data 应用程序实践指南)
    1.4.2. 实现 Core Data Helper 类(Core Data 应用程序实践指南)
    1.4.1. Core Data Helper 简介(Core Data 应用程序实践指南)
    1.4. 为现有的应用程序添加 Core Data 支持(Core Data 应用程序实践指南)
    1.3.2. App Icon 和 Launch Image(Core Data 应用程序实践指南)
    1.3.1. 新建Xcode项目并设置故事板(Core Data 应用程序实践指南)
    php验证邮箱是否合法
    如何使js函数异步执行
  • 原文地址:https://www.cnblogs.com/zzqsblog/p/8022075.html
Copyright © 2011-2022 走看看