码迷,mamicode.com
首页 > 其他好文 > 详细

test 190730 云顶之弈

时间:2019-07-30 21:29:42      阅读:100      评论:0      收藏:0      [点我收藏+]

标签:amp   size   位置   离散化   复杂度   游戏公司   class   sqrt   oid   


问题描述

云顶之弈是一款最近很流行的自走棋游戏,玩家需要抽取卡片提升装备并通过巧妙的布局赢得游戏.

赢得游戏的关键在于良好的策略,但运气也是必不可少的.
游戏公司当然不会放过一个捞金的好机会,于是,如果抽不到想要的卡片,可以在商店购买.
当然,游戏公司也会利用人们的侥幸心理,让他们花钱购买抽卡的机会.商店进行保证,连抽c次一定可以获得想要的卡片.
具体来说,每个光顾商店的人有一个氪金值 和一个欧气值 ,若他的欧气值大于等于c,他会选择连抽c次获得卡片,若他的欧气值小于c,且他的氪金值大于等于卡片的价格p,他会氪金买他想要的卡片.否则他会离开商店.
现在,游戏公司要做的就是定下需要连抽多少次才能保证获得想要的卡片,即一个人连抽c次游戏公司可以赚取$c*w$的利润.游戏公司想要你帮他计算c 定为1到$1+max(b_i)$的最大利润.(p不确定).
输入格式
第一行两个数,n,w,表示光顾商店的人和单次抽取卡片的费用.
接下来n行,每行两个数,表示第i 个人的氪金值 $a_i$和欧气值$b_i$ .
输出格式
一行,共$1+max(b_i)$个数,第i个数表示c=i时的最大利润.
输入样例1
2 1
2 0
0 2
输出样例1
3 4 2
输入样例2
3 1
3 1
2 2
1 3
输出样例2
3 7 7 4
数据范围
$n\leq10^5$,$a_i,b_i\leq10^5$

基本思路思路很好想,枚举c求答案,加上离散化,时间复杂度$O(nmax(a_i))$

可以发现求答案的主要过程抽象为这样一种数据结构,支持给1~x中每个数加上它本身,询问1~n中的最大值

然后自然而然想到要用分块

如果修改的是一个完整块,怎样维护其中的最大值?

我们知道,每个位置对应的值为$i*tag_i+s_i$

修改时,只有$tag_i$会变化,而且单调递增

另外,在每个块内$i$也是单调递增的

是不是有一点点像斜率优化?

把每个元素看作$(i,s_i)$,维护一个下凸包,满足对于$i<j<k$,$\frac{s_i-s_j}{i-j}<\frac{s_j-s_k}{j-k}$

每次修改时,删去$s_i-s_j\leq(j-i)*tag_{block_i}$的

剩下的暴力重建即可,时间复杂度$O(n\sqrt{n})$

很巧妙地在分块中结合了斜率优化的思想

 

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,n_n,w,mxb,mxa;
int block[N],lft[N],rgt[N];
long long tag[N],s[N],maxx[N];
struct person {int a,b;} p[N];
bool cmp(person u,person v) {return u.b<v.b;}
int q[505][505],h[505],t[505];
void update(int r)
{
    int R=block[r];
    for(int i=1;i<R;++i)
    {
        ++tag[i];
        while(h[i]<t[i] && 
            s[q[i][h[i]]]-s[q[i][h[i]+1]]<=
                1ll*(q[i][h[i]+1]-q[i][h[i]])*tag[i]) 
            ++h[i];
        
        maxx[i]=1ll*q[i][h[i]]*tag[i]+s[q[i][h[i]]];
    }
    for(int i=lft[R];i<=r;++i) s[i]+=i;
    for(int i=lft[R];i<=rgt[R];++i) s[i]+=tag[R]*i;
    h[R]=1,t[R]=tag[R]=0;
    for(int i=lft[R];i<=rgt[R];++i)
    {
        while(t[R]>h[R] && 
            1ll*(s[q[R][t[R]]]-s[i])*(q[R][t[R]-1]-q[R][t[R]])>=
                1ll*(q[R][t[R]]-i)*(s[q[R][t[R]-1]]-s[q[R][t[R]]])) --t[R];
        q[R][++t[R]]=i;
    }
    while(h[R]<t[R] && s[q[R][h[R]]]<=s[q[R][h[R]+1]]) ++h[R];
    maxx[R]=s[q[R][h[R]]];
}
long long ask_max()
{
    long long ret=0;
    for(int i=1;i<=n_n;++i) ret=max(ret,maxx[i]);
    return ret;
}
int main()
{
    freopen("could.in","r",stdin); freopen("could.out","w",stdout);
    scanf("%d%d",&n,&w);
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d",&p[i].a,&p[i].b);
        mxa=max(p[i].a,mxa);
    }
    sort(p+1,p+n+1,cmp);
    mxb=p[n].b+1;
    m=sqrt(mxa), n_n=(mxa-1)/m+1;
    for(int i=1;i<=mxa;++i) block[i]=(i-1)/m+1;
    for(int i=1;i<=n_n;++i)
    {
        lft[i]=(i-1)*m+1, rgt[i]=min(i*m,mxa);
        h[i]=1, t[i]=1, q[i][1]=rgt[i];
    }
    int pl=1,pr=1;
    for(int i=1;i<=mxb;++i)
    {
        long long ans=0;
        while(p[pr].b<i && pr<=n) ++pr;
        ans=1ll*i*w*(n-pr+1);
        for(int j=pl;j<pr;++j) update(p[j].a);
        pl=pr;
        printf("%lld ",ans+ask_max());
    }
    return 0;
}

 

test 190730 云顶之弈

标签:amp   size   位置   离散化   复杂度   游戏公司   class   sqrt   oid   

原文地址:https://www.cnblogs.com/w19567/p/11272705.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!