Game——题解

题目大意

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

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

继续玄学!!!
我们实际上只要开个计数数组就Ok了
维护当前最大的数,则这个指针显然是不升的:
如果进来一个大的,立刻就会被干掉了
所以均摊就是 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;
}

猜你喜欢

转载自blog.csdn.net/qq_42403731/article/details/81838160