zoukankan      html  css  js  c++  java
  • CSP-S2020 贪吃蛇

    题目描述


    题解

    70分没想清楚+时间不够=20分

    考场上的奇妙做法:

    假设每条蛇都没有脑子,不管自己的死活往下吃,那么最后会形成一棵操作树,(u,v,t)表示u在t时间吃了v

    显然根不会被吃,所以其相连的有危险,所以它们会放掉自己儿子中时间最大的那个,设其为y父亲为x,则非x外的蛇知道y是最大的,所以如果它们不放的话x必须要放,x也知道别的蛇不会放,所以它也会放了y,并且这样对所有有危险的蛇都是最优的

    然后有一部分蛇会脱离危险,所以它们可以继续往下吃,如此用前缀和优化一下随便维护即可做到O(n)

    问题是怎么O(n)求出操作树,具体见https://blog.csdn.net/EI_Captain/article/details/109552980

    换一种做法(Orz lk),如果一条蛇吃完后不会变成最小的则它一定会吃,因为下一条蛇吃了之后会比自己更小,死得比自己快,所以把锅丢给它

    如果变成最小的,那么往后找出按照这样吃第一条不会变成最小的蛇,那么它一定会吃,下一条一定不吃,下下条一定会吃,按照奇偶性讨论

    用两个队列即可维护,只要没有出现变成最小的话那么max递减min递增,相减得到的递减丢到第二个队列里

    如果变成最小的,那么每次只能跑到末尾否则就停

    时间复杂度O(n)

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define ll long long
    #define file
    using namespace std;
    
    struct type{int s,x;} s1,s2;
    struct Queue{type d[1000001];int h,t;
    	void push(type s) {d[++t]=s;}
    	void pop(bool tp) {if (!tp) ++h; else --t;}
    	void clear() {h=1,t=0;}
    	bool empty() {return h>t;}
    	type head() {return d[h];}
    	type tail() {return d[t];}
    } q[2];
    int a[1000001],T,n,i,j,k,l,I,x,y,ans,I1,I2,sum;
    
    bool operator < (type a,type b) {return a.s<b.s || a.s==b.s && a.x<b.x;}
    bool operator > (type a,type b) {return a.s>b.s || a.s==b.s && a.x>b.x;}
    void swap(int &x,int &y) {int z=x;x=y;y=z;}
    
    int main()
    {
    //	freopen("snakes.in","r",stdin);
    //	#ifdef file
    //	freopen("snakes.out","w",stdout);
    //	freopen("b.out","w",stdout);
    //	#endif
    	
    	scanf("%d",&T);
    	fo(I,1,T)
    	{
    		if (I==1)
    		{
    			scanf("%d",&n);
    			fo(i,1,n) scanf("%d",&a[i]);
    		}
    		else
    		{
    			scanf("%d",&k);
    			fo(i,1,k) scanf("%d%d",&x,&y),a[x]=y;
    		}
    		
    		q[0].clear(),q[1].clear(),ans=n;
    		I1=0,I2=1;
    		fd(i,n,1) q[I1].push(type{a[i],i});
    		while (ans>1)
    		{
    			--ans;
    			if (q[I2].empty() || q[I1].tail()<q[I2].tail()) s2=q[I1].tail(),q[I1].pop(1); else s2=q[I2].tail(),q[I2].pop(1);
    			if (!s2.s) continue;
    			if (q[I2].empty() || q[I1].head()>q[I2].head()) s1=q[I1].head(),q[I1].pop(0); else s1=q[I2].head(),q[I2].pop(0);
    			
    			s1.s-=s2.s;
    			if (q[I1].empty()) swap(I1,I2);
    			q[I2].push(s1);
    			if (q[I1].tail()>s1) break;
    		}
    		if (ans>1)
    		{
    			sum=0;
    			while (sum<ans-1)
    			{
    				if (q[I2].empty() || q[I1].tail()<q[I2].tail()) s2=q[I1].tail(),q[I1].pop(1); else s2=q[I2].tail(),q[I2].pop(1);
    				if (q[I2].empty() || q[I1].head()>q[I2].head()) s1=q[I1].head(),q[I1].pop(0); else s1=q[I2].head(),q[I2].pop(0);
    				
    				s1.s-=s2.s;
    				if (q[I1].empty()) swap(I1,I2);
    				if (!q[I1].empty() && q[I1].tail()<s1 || !q[I2].empty() && q[I2].tail()<s1) break;
    				q[I2].push(s1);
    				++sum;
    			}
    			sum+=sum==(ans-1);
    			ans+=!(sum&1);
    		}
    		
    		printf("%d
    ",ans);
    	}
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    什么是ORM
    ORM优缺点
    Azure 中快速搭建 FTPS 服务
    连接到 Azure 上的 SQL Server 虚拟机(经典部署)
    在 Azure 虚拟机中配置 Always On 可用性组(经典)
    SQL Server 2014 虚拟机的自动备份 (Resource Manager)
    Azure 虚拟机上的 SQL Server 常见问题
    排查在 Azure 中新建 Windows 虚拟机时遇到的经典部署问题
    上传通用化 VHD 并使用它在 Azure 中创建新 VM
    排查在 Azure 中新建 Windows VM 时遇到的部署问题
  • 原文地址:https://www.cnblogs.com/gmh77/p/13956086.html
Copyright © 2011-2022 走看看