CSP-S 2020 T4贪吃蛇

题目大意

题解

这题考场上一看就感觉很可做,非常快就想到了简单又自然的70分方法,但是将大量的时间都放在了想办法优化到满分上,导致T3都没时间想。

做法不难,容易发现,如果当前的\(Max\)吃掉\(Min\)以后不是最小的,那么一定可以吃,因为下一个吃完以后一定会比他小,也就是会先被吃掉,所以只需要把问题交给下一条蛇就行了。

然后可以发现,如果当前吃完以后变成最小的了,那么就要看下一个会不会选择吃掉它,而下一个又要再需要继续看接下来的蛇的操作。

容易总结出一条结论,当现在吃完以后变成最小的以后,只需要判断第一个吃完不是最小的蛇与当前轮数的奇偶性就行了。

然后接下来的问题就比较简单了,可以用两个队列来维护。一个队列维护还未被操作的蛇,一个队列维护已经操作后的蛇,两个队列都是单调的,就可以以此来维护\(Max\)\(Min\)了。

当只剩两条蛇的时候要特判,此时显然是可以吃的。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 3000010
using namespace std;
int T,n,i,k,x,y,ans,l,r,l1,r1;
struct node{
	int val,id;
}lp[N],a[N],p[N];
inline int read(){
	int x=0;
	char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x;
}
int cmp(node x,node y){
	if (x.val!=y.val) return x.val>y.val;
	return x.id>y.id;
}
node getmax(){
	if (l>r) return p[l1++];
	if (l1>r1) return a[l++];
	if (cmp(a[l],p[l1])) return a[l++];
	else return p[l1++];
}
node getmin(){
	if (l>r) return p[r1--];
	if (l1>r1) return a[r--];
	if (cmp(a[r],p[r1])==0) return a[r--];
	else return p[r1--];
}
node getmin2(){
	if (l>r) return p[r1];
	if (l1>r1) return a[r];
	if (cmp(a[r],p[r1])==0) return a[r];
	else return p[r1];
}
void solve(){
	l=1,r=n,l1=1,r1=0;
	int tot;
	node Max,Min;
	ans=n;
	while (true){
		if (ans<=2){
			ans=1;
			return;
		}
		Max=getmax();
		Min=getmin();
		Max.val-=Min.val;
		if (cmp(Max,getmin2())==0){
			tot=1;
			p[++r1]=Max;
			while (true){
				if (ans-tot<=2) {
					tot++;
					if (tot%2==1) ans--;
					return;
				}
				Max=getmax();
				Min=getmin();
				Max.val-=Min.val;
				tot++;
				if (cmp(Max,getmin2())){
					if (tot%2==1) ans--;
					return;
				}
				else
					p[++r1]=Max;
			}
		}
		else{
			ans--;
			p[++r1]=Max;
		}
	}
}
int main(){
	freopen("snakes.in","r",stdin);
	freopen("snakes.out","w",stdout);
	T=read();
	n=read();
	for (i=1;i<=n;i++) lp[i].val=read(),lp[i].id=i;
	for (i=1;i<=n/2;i++) swap(lp[i],lp[n-i+1]);
	for (i=1;i<=n;i++) a[i]=lp[i];
	solve();
	printf("%d\n",ans);
	T--;
	while (T--){
		k=read();
		for (i=1;i<=k;i++) x=read(),y=read(),lp[n-x+1].val=y;
		for (i=1;i<=n;i++) a[i]=lp[i];
		solve();
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2020-11-12 19:26  Mohogany  阅读(227)  评论(0编辑  收藏  举报