zoukankan      html  css  js  c++  java
  • LG 7078 贪吃蛇

    [CSP-S2020] 贪吃蛇

    题面

    题目描述

    草原上有 (3leq nleq 10^6) 条蛇,编号分别为 (1, 2, ldots , n) 。初始时每条蛇有一个体力值 (a_i) ,我们称编号为 (x) 的蛇实力比编号为 (y) 的蛇强当且仅当它们当前的体力值满足 (a_x > a_y) ,或者 (a_x = a_y)(x > y)

    接下来这些蛇将进行决斗,决斗将持续若干轮,每一轮实力最强的蛇拥有选择权,可以选择吃或者不吃掉实力最弱的蛇:

    1. 如果选择吃,那么实力最强的蛇的体力值将减去实力最弱的蛇的体力值,实力最弱的蛇被吃掉,退出接下来的决斗。之后开始下一轮决斗。
    2. 如果选择不吃,决斗立刻结束。

    每条蛇希望在自己不被吃的前提下在决斗中尽可能多吃别的蛇(显然,蛇不会选择吃自己)。

    现在假设每条蛇都足够聪明,请你求出决斗结束后会剩几条蛇。

    本题有多组数据,对于第一组数据,每条蛇体力会全部由输入给出,之后的每一组数据,会相对于上一组的数据,修改一部分蛇的体力作为新的输入。

    题解

    首先要读题,搞清楚这个决斗到底是什么东西:

    这是每轮 (max-min) 的连续过程, (max) 玩家只能选择中止这个过程,而不能改变该过程。

    决斗的过程就是不断 (max-min) 至一个元素之过程的前缀。

    下一步观察在决斗结束时,活下来的蛇有什么性质,(看反面),注意到死去的蛇注定没有获得过主动权。(否则他会在之前弃权结束掉决斗)进一步分析什么时候第一条有过主动权的蛇成为最弱蛇(称该蛇为关键蛇),如没有这样的蛇,决斗在只有一个幸存者时结束。

    在此之前,经历过决斗的蛇都不成为最弱蛇,故而每轮决斗的 (min) 单增,以及每轮决斗的 (max) 单减是显然的,于是每轮生成的 (max-min) 是单减的,进一步得到关键蛇恰在吃掉最弱蛇后成为最弱蛇。

    现在决斗的结束只有两种可能了:关键蛇弃权而不成为最弱蛇,或者关键蛇确信决斗会在下一轮结束而吃掉最弱蛇。

    (由于关键蛇必不会死去,决斗不能在此之后终止;又由此,决斗不会在此前结束)

    这推出 (max-min) 不成为新的 (min) ,则该轮必会进行。

    接下来判定决斗是否在下一轮结束,只需要从下一轮为起始再次运用上述结论。但这次我们只关心起始轮会不会发生了:只有吃掉关键蛇的蛇因此成为最弱蛇,我们才需要递归地判定下去。

    总结以下前述的分析,决斗将在 (max-min) 不成为新的 (min) 时持续下去,判断第一个新 (min) 是否会出现,其出现要求从它开始恰有连续偶数轮 (max-min) 成为新的 (min) (如新的 (min) 是最后一个数,不认为他是新 (min)

    至此我们分析完了此题,只需要模拟决斗的过程并按上述方式进行判断即可。需要维护的是取 (max) ,取 (min) ,插入一个数;根据前述的 (max-min) 的单调性,可以用一个队列维护新产生的数,复杂度 (mathcal{O}(n))

    多组数据有点小坑,只有 (Tleq 10) 组,实际上直接每一组单独做就可以,不必多想。

    代码

    //https://www.luogu.com.cn/problem/P7078
    //20211103 nksbwen
    
    #include <cstdio>
    #include <cstring>
    
    const int MAXN=1000111;
    
    int T;
    int N;
    
    struct Pair{
    	int v, id;
    };
    bool operator < (const Pair &A, const Pair &B){
    	return (A.v==B.v)?A.id<B.id:A.v<B.v;
    }
    bool operator > (const Pair &A, const Pair &B){
    	return (A.v==B.v)?A.id>B.id:A.v>B.v;
    }
    Pair operator - (const Pair &A, const Pair &B){
    	return Pair{A.v-B.v, A.id};
    }
    Pair A[MAXN], B[MAXN], C[MAXN];
    int Bl, Br, Cl, Cr;
    
    int Deal(){
    	int Tag=0, Tmp;
    	while((Br-Bl+1)+(Cr-Cl+1)>1){
    		if(Cl>Cr || (Br>=Bl && B[Br]>C[Cl])){
    			//max=B[Br];
    			if(Cl>Cr || (Br>=Bl && B[Bl]<C[Cr])){
    				//min=B[Bl];
    				// printf("%d %d %d %d
    ", B[Bl].v, B[Bl].id, B[Br].v, B[Br].id);
    				C[++Cr]=B[Br--]-B[Bl++];
    			}
    			else{
    				//min=C[Cr];
    				C[Cr]=B[Br--]-C[Cr];
    			}
    		}
    		else{
    			//max=C[Cl];
    			if(Cl>Cr || (Br>=Bl && B[Bl]<C[Cr])){
    				//min=B[Bl];
    				C[++Cr]=C[Cl++]-B[Bl++];
    			}
    			else{
    				//min=C[Cr];
    				C[Cr]=C[Cl++]-C[Cr];
    			}
    		}
    		if((Bl<=Br && C[Cr]>B[Bl]) || (Cl<Cr && C[Cr]>C[Cr-1]) || (Bl>Br && Cl==Cr)){
    			if(Tag)	break;
    			else	continue;
    		}
    		else	++Tag;
    		if(Tag==1)	Tmp=(Br-Bl+1)+(Cr-Cl+1)+1;
    	}
    	return (Tag)?(Tmp-!(Tag&1)):1;
    }
    
    int main(){
    	
    	scanf("%d", &T);
    	scanf("%d", &N);
    	for(int i=1;i<=N;++i){
    		scanf("%d", &A[i].v);
    		A[i].id=i;
    	}
    	memcpy(B+1, A+1, sizeof(Pair)*N);Bl=1;Br=N;Cl=1;Cr=0;
    	printf("%d
    ", Deal());
    	for(int i=1, k;i<T;++i){
    		scanf("%d", &k);
    		for(int j=1, a, b;j<=k;++j){
    			scanf("%d%d", &a, &b);
    			A[a].v=b;
    		}
    		memcpy(B+1, A+1, sizeof(Pair)*N);Bl=1;Br=N;Cl=1;Cr=0;
    		printf("%d
    ", Deal());
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    SpringMVC 配置文件详解
    SpringMVC 入门demo
    SpringMVC 简介
    解决IDEA部署web项目时,jar包拷贝不全的问题
    录制 带鼠标光圈效果的视频
    Spring整合Junit4进行单元测试
    Illegal invocation with document.querySelector [duplicate]
    html-webpack-template, 一个更好的html web service插件
    Script error.解决方法
    ios9 safari currentTime audio bug
  • 原文地址:https://www.cnblogs.com/Pickupwin/p/LG-7078.html
Copyright © 2011-2022 走看看