洛谷P7078 贪吃蛇
CSP-S 2020 T4 贪吃蛇
分析
加入我们当前最强的蛇为\(xcg\),第二强的蛇为\(ybr\),最弱的蛇为\(jyy\),第二弱的蛇为\(ych\),当然\(gc\)更弱 【过弱已隐藏】
对于我们当前的最强蛇\(xcg\),有以下几种情况
- \(xcg\)吃掉\(jyy\)之后,他的体力值仍大于\(ybr\)的体力值,因为\(xcg\)很贪心,会直接吃掉\(jyy\),完全不必担心自己的死亡
- \(xcg\)吃掉\(jyy\)之后,他的体力值虽然小于\(ybr\)的体力值,但是仍然不是最小的(此时的体力最小的蛇为\(ych\)),所以就算是第二轮\(ybr\)打算吃蛇,也不会去考虑吃掉\(xcg\),而是去吃\(ych\),所以\(xcg\)的生命不会受到任何威胁,而且\(ybr\)吃掉\(ych\)之后的体力值一定比\(xcg\)少
- \(xcg\)吃掉\(jyy\)之后,他的体力值直接最小,而且此时\(ybr\)在第二轮吃掉\(xcg\)不会导致\(ybr\)第三轮的死亡,那么也就是说,如果\(xcg\)过于贪心,会导致他在下一轮沦为他人的食物,这时的\(xcg\)变得十分机智,他不会去吃\(jyy\),而是直接将游戏结束
- \(xcg\)吃掉\(jyy\)之后,他的体力值直接最小,但是此时\(ybr\)会因为在第二轮吃掉\(xcg\)导致\(ybr\)第三轮的死亡,那么在下一轮到来时,\(xcg\)并不会被\(ybr\)吃掉,因为他也想活。。。此时的\(xcg\)打算在钢丝上跳舞,直接吃掉\(ych\)满足自己贪吃的欲望
显然,我们当前的贪吃蛇吃与不吃是取决于这一轮和下一轮时是否会被其他蛇吃掉
对于\(ybr\)是否吃的问题,又可以分成以上两种情况进行讨论,假如\(ybr\)吃后不是最弱蛇,那么\(ybr\)会选择吃,\(xcg\)预判到\(ybr\)的操作,所以选择不吃来避免死亡。
简单分析一下 (当然我看的是其他人的题解才会的) ,会发现,我们此时\(xcg\)吃或不吃由之后这个序列的长度的奇偶性决定。
并且这个序列长度\(\geqslant2\),所以序列中必定有一个不吃,所以当游戏进入情况二(最强蛇吃掉最弱蛇变成最弱蛇)后,不会重新回到情况一(最强蛇吃掉最弱蛇不会变成最弱蛇),而是会再吃\(0\)或\(1\)次,然后结束。
具体做法就是模拟这两个阶段。
我选择的是用两个双端队列维护蛇的序列,使其的体力值单调,一头强一头弱。那么我们每次从两个队列尾取出最强,从某个队列中取出最弱,不断重复即可。
因为新产生的蛇的体力值也具有单调性,所以不需要用复杂度为\(log(n)\)数据结构去再次进行维护。
\(Code\)
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int a=0,b=1;
char c=getchar();
while(!isdigit(c))
{
if(c=='-')
b=-1;
c=getchar();
}
while(isdigit(c))
{
a=(a<<1)+(a<<3)+(c^48);
c=getchar();
}
return a*b;
}
int T,n,a[1000005],ans,cnt;
deque<pair<int,int> >q1,q2;
inline void clear()
{
q1.clear();
q2.clear();
ans=0;
cnt=0;
}
int main()
{
T=read();
for(int i=1;i<=T;i++)
{
clear();
if(i==1)
{
n=read();
for(int j=1;j<=n;j++)
a[j]=read();
}
else
{
int k=read();
for(int j=1;j<=k;j++)
{
int x=read(),y=read();
a[x]=y;
}
}
for(int i=1;i<=n;i++)
q1.push_back(make_pair(a[i],i));
while(1)
{
if(q1.size()+q2.size()==2)
{
ans=1;
break;
}
int minn,maxn,now;
minn=q1.front().first;
q1.pop_front();
if(q2.empty()||q1.size()&&q1.back()>q2.back())
{
maxn=q1.back().first;
now=q1.back().second;
q1.pop_back();
}
else
{
maxn=q2.back().first;
now=q2.back().second;
q2.pop_back();
}
pair<int,int>snake=make_pair(maxn-minn,now);
if(snake>q1.front())
q2.push_front(snake);
else
{
ans=q1.size()+q2.size()+2;
while(1)
{
cnt++;
if(q1.size()+q2.size()==1)
{
if(!(cnt%2))
ans--;
break;
}
int qwq,NOW;
if(q2.empty()||q1.size()&&q1.back()>q2.back())
{
qwq=q1.back().first;
NOW=q1.back().second;
q1.pop_back();
}
else
{
qwq=q2.back().first;
NOW=q2.back().second;
q2.pop_back();
}
snake=make_pair(qwq-snake.first,NOW);
if(snake<q1.front()&&(q2.empty()||snake<q2.front()))
;
else
{
if(!(cnt%2))
ans--;
break;
}
}
break;
}
}
printf("%d\n",ans);
}
return 0;
}