洛谷 P7078 - [CSP-S2020] 贪吃蛇(贪心)
题意:
- 有 \(n\) 条蛇,每条蛇有个实力 \(a_i\)
- 我们称编号为 \(x\) 的蛇比编号为 \(y\) 的蛇强,当且仅当 \(a_x>a_y\) 或 \(a_x=a_y\) 且 \(x>y\)。
- 每次实力最强的蛇可以选择吃掉实力最弱的蛇或者不吃,如果实力最强的蛇选择吃,那么它的实力会减去实力最弱的蛇的实力,实力最弱的蛇将消失。
- 假设每条蛇都会选择最优策略(在保证自己不被吃的条件下吃掉尽可能多的别的蛇),问最后会剩下多少条蛇。
- \(\sum n\le 10^7\)
薅洛谷题解 ing
首先我们来挖掘一些性质。可以发现,如果一条蛇吃完最弱的蛇之后不是最弱的蛇,那么它一定会选择吃。因为如果最强的蛇吃完最弱的蛇之后还是最强的蛇,那它不吃白不吃。否则,下一步最强的蛇的实力肯定是弱于原来最强的蛇的实力的,并且由于这条蛇吃完之后不是最弱的蛇,最弱的蛇的实力也强于原来最弱的蛇的实力,也就是说,下一步最强的蛇吃完最弱的蛇之后,肯定比当前最强的蛇吃完最弱的蛇之后的实力更菜,也就是说,如果下一步最强的蛇死了,那它死的时间肯定比当前这条蛇死的时间早,而下一步最强的蛇肯定会选择保住自己,因此下一步最强的蛇一定不会死,故就算这一步最强的蛇吃了最弱的蛇,它也不会死,因此它肯定会选择吃。
那么如果一条蛇吃了最弱的蛇之后变成了最弱的蛇之后怎么办呢?显然,如果一条蛇吃了最弱的蛇之后变成了最弱的蛇,而下一步最强的蛇吃了最弱的蛇之后不是最弱的蛇,或者下一步只剩两条蛇,那它肯定不会吃,因为如果它吃了最弱的蛇,那么下一步最强蛇可以安心吃掉最弱的蛇,它也就挂掉了。
我们再往前回溯一格,如果一条蛇吃了最弱的蛇后,下一步最强的蛇满足之前所述的状态,那么这条蛇会选择吃掉最弱的蛇,因为下一步最强蛇不敢吃最弱的蛇,否则它就会死。因此这一步最强的蛇可以放心大胆地吃,而下一步的蛇又不敢吃,因此这种情况总蛇数会少一。
如果再往前回溯一格那也可以得到类似的结论,如果最强蛇吃完最弱蛇之后回到了上一步所说的状态,那它又不敢吃了,因为吃了之后下一步最强蛇可以安心吃最弱蛇。
我们可以发现,出现最强蛇吃了最弱蛇的情况之后,答案会不会减少一,取决于当前局面到最强蛇能够安心吃掉最弱蛇经过的轮数的奇偶性,如果不算“第一次出现最强蛇吃了最弱蛇变成最弱蛇”这一轮,算上“最强蛇能够安心吃掉最弱蛇”这一轮之后,轮数是偶数,那么答案会减少一。因此我们考虑将整个过程分为两个部分:
- 第一部分:最强蛇吃完最弱蛇之后都不是最弱蛇,放心大胆吃,答案减一
- 第二部分:出现某个最强蛇吃完最弱蛇之后是最弱蛇:重复上面的过程直到出现一条最强蛇可以放心大胆地吃掉最弱蛇,根据第二部分持续的轮数判断答案是否减一。
直接 set 维护大概可以拿到 70 分的好成绩。考虑优化。我们建立两个 deque,分别称作 \(q_1,q_2\),维护现在没有吃过别的蛇,和现在已经吃过别的蛇的蛇的实力,实力从队首到队尾依次递减,然后考虑如下过程:
- 第一部分:
- 每次取出 \(q_1,q_2\) 队尾元素中的较强者作为最强蛇,以及 \(q_1\) 队首元素作为最弱蛇,由于这一部分中所有最强蛇吃完最弱蛇后,都不是最弱蛇,因此这一轮的最弱蛇肯定没有吃过别人,即,在队列 \(q_1\) 中。
- 我们计算出最强蛇吃完最弱蛇的实力,如果小于现在 \(q_1\) 队首的实力就进入第二部分,否则将它塞入 \(q_2\) 队首。根据之前的推论,此时吃完最弱蛇的最强蛇的实力,肯定比上一轮吃完最弱蛇的最强蛇实力更菜。
- 第二部分:
- 我们直接取出 \(q_1,q_2\) 的队尾,由于最弱蛇就是上一轮中吃完最弱蛇的最强蛇,因此我们不用取出 \(q_1/q_2\) 的队首元素,而是直接取出上一次吃掉别人的蛇即可。
- 还是计算出最强蛇吃完最弱蛇的实力,如果此时这条蛇的实力比当前最弱蛇的实力强就退出,根据第二部分轮数的奇偶性判断是否令答案减一。否则继续重复上一步的过程。
时间复杂度 \(\sum n\)。
const int MAXN=1e6;
int n,a[MAXN+5];bool fst=0;
deque<pii> q1,q2;
pii getmx(){
pii p;
if(q1.empty()) return p=q2.back(),q2.ppb(),p;
if(q2.empty()) return p=q1.back(),q1.ppb(),p;
if(q2.back()>q1.back()) return p=q2.back(),q2.ppb(),p;
return p=q1.back(),q1.ppb(),p;
}
void solve(){
if(!fst){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
} else {
int c;scanf("%d",&c);
while(c--){
int x,y;scanf("%d%d",&x,&y);
a[x]=y;
}
} fst=1;
while(!q1.empty()) q1.ppb();
while(!q2.empty()) q2.ppb();
for(int i=1;i<=n;i++) q1.push_back(mp(a[i],i));
// for(int i=1;i<=n;i++) printf("%d%c",a[i]," \n"[i==n]);
while(1){
if(q1.size()+q2.size()<=2) return puts("1"),void();
pii p=getmx();
int y=q1.front().fi;q1.pop_front();
if(q1.empty()||mp(p.fi-y,p.se)<q1.front()){
int cnt=0,res=q1.size()+q2.size()+1,pre=p.fi-y;
while(1){
cnt++;
if(q1.size()+q2.size()<2){
if(cnt&1) res++;
printf("%d\n",res);
return;
} pii nwp=getmx();
if((q1.empty()||mp(nwp.fi-pre,nwp.se)<q1.front())&&
(q2.empty()||mp(nwp.fi-pre,nwp.se)<q2.front()));
else {
if(cnt&1) res++;
printf("%d\n",res);
return;
} pre=nwp.fi-pre;
}
} else q2.push_front(mp(p.fi-y,p.se));
} assert(0);
}
int main(){
// freopen("snakes4.in","r",stdin);
int qu;scanf("%d",&qu);
while(qu--) solve();
return 0;
}

浙公网安备 33010602011771号