[PA 2010] Termites
[PA 2010] Termites
整个结构可以被刻画成 \(\geq 0\) 个双端队列和 \(\leq 2\) 个栈,每次可以选择一个元素弹出。
一个简单的策略,每次选择最大的数弹出,但是这样显然错误,比如 \([0,1,2,10,3,0]\)。
考虑这种情况出现在取了 \(x\) 后发现把 \(y \geq x\) 让给了对面,这是我们不希望看到的。
也就是说,如果存在 \(x \leq y \geq z\),则先手无论如何取都会将 \(y\) 让给对方。
此时先手得到 \(x+z\),后手得到 \(y\),故可以将其看作一个 \(x+z-y\) 的物品。
不断合并之后得到单谷序列,在单谷序列上这个做法显然是有道理的,可以 \(O(n \log n)\)。
然而有 stack,将两个 stack 的底端拼在一起,中间加入 \(-\infty\) 即可。
//Ad astra per aspera
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
long long a[1000010],b[1000010],c[1000010],stk[1000010],top;
int n_b,n_c;
int key_pos[1000010][2],key_cnt;
struct Node{
int num1,num2;
};
bool operator <(const Node &lhs,const Node &rhs){
return b[key_pos[lhs.num1][lhs.num2]]<b[key_pos[rhs.num1][rhs.num2]];
}
void add(){
top=0;
for(int i=1;i<=n_c;i++){
while(top>=2 && stk[top-1]<=stk[top] && stk[top]>=c[i]){
c[i]+=stk[top-1]-stk[top];
top-=2;
}
stk[++top]=c[i];
}
if(top){
key_cnt++;
key_pos[key_cnt][0]=0x3f3f3f3f;
key_pos[key_cnt][1]=-0x3f3f3f3f;
for(int i=1;i<=top;i++){
n_b++;
b[n_b]=stk[i];
key_pos[key_cnt][0]=min(key_pos[key_cnt][0],n_b);
key_pos[key_cnt][1]=max(key_pos[key_cnt][1],n_b);
}
}
}
int main(){
long long sum=0;
int n,min_0=0x3f3f3f3f,max_0=-0x3f3f3f3f;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum+=a[i];
if(a[i]==0){
min_0=min(min_0,i);
max_0=max(max_0,i);
}
}
int lst_pos=min_0;
for(int i=min_0+1;i<=max_0;i++){
if(a[i]==0){
n_c=0;
for(int j=lst_pos+1;j<=i-1;j++){
c[++n_c]=a[j];
}
add();
lst_pos=i;
}
}
n_c=0;
for(int i=max_0+1;i<=n;i++){
c[++n_c]=a[i];
}
c[++n_c]=-0x3f3f3f3f3f3f3f3f;
for(int i=1;i<=min_0-1;i++){
c[++n_c]=a[i];
}
add();
priority_queue<Node> pq;
for(int i=1;i<=key_cnt;i++){
pq.push((Node){i,0});
pq.push((Node){i,1});
}
long long d=0;
bool flg=true;
while(!pq.empty()){
int id=pq.top().num1,cmd=pq.top().num2;
pq.pop();
if(key_pos[id][0]>key_pos[id][1]){
continue;
}
long long num;
if(cmd==0){
num=b[key_pos[id][0]++];
}
else{
num=b[key_pos[id][1]--];
}
if(flg){
d+=num;
}
else{
d-=num;
}
if(key_pos[id][0]<=key_pos[id][1]){
if(cmd==0){
pq.push((Node){id,0});
}
if(cmd==1){
pq.push((Node){id,1});
}
}
flg=!flg;
}
if(d<0){
d+=0x3f3f3f3f3f3f3f3f;
}
else{
d-=0x3f3f3f3f3f3f3f3f;
}
printf("%lld %lld",(sum+d)/2,(sum-d)/2);
return 0;
}

浙公网安备 33010602011771号