zoukankan      html  css  js  c++  java
  • P7078-[CSP-S2020]贪吃蛇【贪心,队列】

    正题

    题目链接:https://www.luogu.com.cn/problem/P7078


    题目大意

    (n)条贪吃蛇,第(i)条长度为(a_i),每次最长的那条蛇可以选择吃掉最短的那条蛇,然后自己的长度减去其长度,也可以不吃然后结束游戏。

    现在询问在所有蛇都希望吃的蛇最多且自己不会被吃的情况下最后会留下多少条蛇。

    (T)次每次修改(k)个值,保证修改前后(a)单调不降。

    (3leq nleq 10^6,1leq Tleq 10,0leq kleq 10^5)


    解题思路

    考虑一条蛇什么时候会选择不吃。

    首先如果一条蛇吃掉别的蛇之后它不是最小的蛇,那么它一定会去吃这条蛇。假设最大的和次大的蛇长度为(a,b),最小和次小的为(c,d),由于(a-c>d)又有(b-d<a-c)那么显然如果(b)蛇吃了肯定会比(a)蛇先死,那么如果(b)会死那么它肯定不吃(d)那么(a)蛇显然也不会被吃。

    如果一条蛇吃了别的蛇后它是最小的蛇会发生什么。记蛇从大到小排序为(a,b,c,...),那么如果蛇(a)吃了最小的后它成最小的了且(b)会吃,那么(a)肯定不吃。此时我们就需要判断(b)是否吃了,同理的,如果(b)吃了最小的之后它也是最小的那么就需要考虑(c)吃不吃最小的。

    此时递归下去直到一条吃了之后不是最小的或者只剩两条蛇时就结束了。

    然后用类似于合并果子那样的方法用两个队列维护即可。

    时间复杂度:(O(Tn))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    using namespace std;
    const int N=1e6+10;
    int T,n,a[N],w[N],q1[N],q2[N];
    int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    	return x*f;
    }
    bool cmp(int x,int y)
    {return (w[x]==w[y])?x<y:w[x]<w[y];}
    void solve(){
    	int h1=1,t1=n,h2=1,t2=0,v,p;T--;
    	for(int i=1;i<=n;i++)w[q1[n-i+1]=i]=a[i];
    	while(1){
    		if(t1-h1+1+t2-h2+1==2){printf("%d
    ",1);return;}
    		if(t2-h2+1<=0||t1-h1+1>0&&cmp(q2[h2],q1[h1])){
    			v=w[p=q1[h1]];p=q1[h1];h1++;
    			if(t2-h2+1<=0||t1-h1+1>0&&cmp(q1[t1],q2[t2]))v-=w[q1[t1]],t1--;
    			else v-=w[q2[t2]],t2--;
    		}
    		else{
    			v=w[p=q2[h2]];h2++;
    			if(t2-h2+1<=0||t1-h1+1>0&&cmp(q1[t1],q2[t2]))v-=w[q1[t1]],t1--;
    			else v-=w[q2[t2]],t2--;
    		}
    		w[p]=v;
    		if((t2-h2+1<=0||cmp(p,q2[t2]))&&(t1-h1+1<=0||cmp(p,q1[t1])))
    			{q2[++t2]=p;break;}
    		q2[++t2]=p;
    	}
    	int cnt=0,f=t2-h2+1+t1-h1+1;
    	while(1){
    		cnt++;
    		if(t1-h1+1+t2-h2+1==2){printf("%d
    ",f+(cnt&1));return;}
    		if(t2-h2+1<=0||t1-h1+1>0&&cmp(q2[h2],q1[h1])){
    			v=w[p=q1[h1]];p=q1[h1];h1++;
    			if(t2-h2+1<=0||t1-h1+1>0&&cmp(q1[t1],q2[t2]))v-=w[q1[t1]],t1--;
    			else v-=w[q2[t2]],t2--;
    		}
    		else{
    			v=w[p=q2[h2]];h2++;
    			if(t2-h2+1<=0||t1-h1+1>0&&cmp(q1[t1],q2[t2]))v-=w[q1[t1]],t1--;
    			else v-=w[q2[t2]],t2--;
    		}
    		w[p]=v;
    		if((t2-h2+1<=0||cmp(p,q2[t2]))&&(t1-h1+1<=0||cmp(p,q1[t1])))
    			{q2[++t2]=p;continue;}
    		printf("%d
    ",f+(cnt&1));return;
    	}
    	return;
    }
    int main()
    {
    	T=read();n=read();
    	for(int i=1;i<=n;i++)a[i]=read();
    	solve();
    	while(T){
    		int k=read();
    		while(k--){
    			int x=read(),w=read();
    			a[x]=w;
    		}
    		solve();
    	}
    	return 0;
    }
    
  • 相关阅读:
    JS URL传中文参数引发的乱码问题
    git (转载)
    php webservice
    php date之间的相互转换
    在图片上加字符-base64转图片-图片转base64
    转:微软面试一百题
    2014-8-17 note
    some base knowledge
    introduction
    Centos6.6 编译安装nginx
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15399511.html
Copyright © 2011-2022 走看看