Game——题解

6 篇文章 0 订阅
4 篇文章 0 订阅

题目大意

两人玩游戏,先往集合里塞 p p 个数a[1,p]
A取个数加入自己分数,再往集合里塞接下来的数
B取个数加入自己分数,再往集合里塞接下来的数
……
两人都选最优策略,求最后A-B的分数差
n<=100000,ai<=100000,pi<=n,k()<=20002s n <= 100000 , a i <= 100000 , p i <= n , k ( 询 问 次 数 ) <= 2000 , 2 s

暴力没得说,堆 log l o g 一下
然后,上高端数据结构?
好像都是 log l o g 级的,还有一个常数媲美 log l o g 的斐波那契堆。。

继续玄学!!!
我们实际上只要开个计数数组就Ok了
维护当前最大的数,则这个指针显然是不升的:
如果进来一个大的,立刻就会被干掉了
所以均摊就是 O(max(ai)) O ( m a x ( a i ) )

#pragma GCC optimize(2)
#include<cstdio>
#include<algorithm>
#define gt() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
#define __R register
#define LL long long
using namespace std;
static char buf[1000000],*p1=buf,*p2=buf;
const int maxn=(1e5)+5;
int n,Q,p,a[maxn],hsh[maxn];LL S;
inline int read(){
    int ret=0;char ch=gt();
    while(ch<'0'||ch>'9') ch=gt();
    while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=gt();
    return ret;
}
void write(LL x){if(x<0) x=-x,putchar('-');if(x<10) putchar(x+'0');else write(x/10),putchar(x%10+'0');}
int main(){
    n=read(),Q=read();
    for(__R int i=1;i<=n;i++) S+=(a[i]=read());
    LL now;int lst;bool flg;
    while(Q--){
        p=read(),lst=0,flg=(p&1);
        for(__R int i=1;i<=p;i++) hsh[a[i]]++,lst=a[i]>lst?a[i]:lst;
        now=lst,hsh[lst]--;
        for(__R int i=p+1;i<=n;i++){
            while(lst&&!hsh[lst]) lst--;
            if(a[i]>=lst){if((i&1)==flg) now+=a[i];}
              else{hsh[a[i]]++;if((i&1)==flg) now+=lst;hsh[lst]--;}
        }
        for(__R int i=n+1;lst;i++){
            while(lst&&!hsh[lst]) lst--;
            if((i&1)==flg) now+=lst;
            hsh[lst]--;
        }
        write(now-(S-now)),putchar('\n');
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值