zoukankan      html  css  js  c++  java
  • 【XSY2787】Mythological VII 贪心

    题目描述

      有两个指针(l,r),初始时(l=r=k)

      给你(a_1,ldots,a_n),你要移动(l,r)(l)只能每次向左移一个数,(r)只能向右移一个数,要求任意时刻((l,r])这个区间内的数的和(leq 0)

      求(l,r)能否都移动到端点。

      (nleq 100000)

    题解

      求前缀和(s),约束转化为任意时刻(s_lgeq s_r)

      每一个时刻的决策是:

      如果(l)能在合法的情况下移动到(l'),满足(s_{l'}>s_l),且是所有合法的位置中最大的,就把(l)移到(l')(r)同理。

      如果左边的最小值(<)右边的当前位置,就无解。

      否则只能贪心移动了。这种情况左边右边剩下的(s)都在([s_l,s_r])内。

      如果左边的最大值小于右边的最大值,就把(r)向右移一位,否则就把(l)向左移一位。

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

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    ll s[100010];
    ll a[100010];
    int fl[100010];
    int fr[100010];
    ll premax[100010];
    ll sufmax[100010];
    ll premin[100010];
    ll sufmin[100010];
    const ll inf=0x3fffffffffffffffll;
    int sl1[100010];
    ll sl2[100010];
    int sr1[100010];
    ll sr2[100010];
    int st[100010];
    int top;
    int solve()
    {
    	int n,k;
    	scanf("%d%d",&n,&k);
    	s[0]=0;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lld",&a[i]);
    		s[i]=s[i-1]+a[i];
    	}
    	premax[0]=-inf;
    	premin[0]=inf;
    	for(int i=1;i<=n;i++)
    	{
    		premax[i]=max(s[i],premax[i-1]);
    		premin[i]=min(s[i],premin[i-1]);
    	}
    	sufmax[n+1]=-inf;
    	sufmin[n+1]=inf;
    	for(int i=n;i>=1;i--)
    	{
    		sufmax[i]=max(s[i],sufmax[i+1]);
    		sufmin[i]=min(s[i],sufmin[i+1]);
    	}
    	top=0;
    	for(int i=1;i<=n;i++)
    	{
    		sl2[i]=s[i];
    		while(top&&s[st[top]]<s[i])
    		{
    			sl2[i]=min(sl2[i],sl2[st[top]]);
    			top--;
    		}
    		if(top)
    			sl1[i]=st[top];
    		else
    			sl1[i]=i;
    		st[++top]=i;
    	}
    	top=0;
    	for(int i=n;i>=1;i--)
    	{
    		sr2[i]=s[i];
    		while(top&&s[st[top]]>s[i])
    		{
    			sr2[i]=max(sr2[i],sr2[st[top]]);
    			top--;
    		}
    		if(top)
    			sr1[i]=st[top];
    		else
    			sr1[i]=i;
    		st[++top]=i;
    	}
    	int l=k,r=k;
    	while(1)
    	{
    		if(l!=1&&sl1[l]!=l&&sl2[l]>=s[r])
    		{
    			l=sl1[l];
    			continue;
    		}
    		if(r!=n&&sr1[r]!=r&&sr2[r]<=s[l])
    		{
    			r=sr1[r];
    			continue;
    		}
    		if(l==1)
    		{
    			if(sufmax[r]>s[l])
    				return 0;
    			return 1;
    		}
    		if(r==n)
    		{
    			if(premin[l]<s[r])
    				return 0;
    			return 1;
    		}
    		if(premax[l-1]<sufmax[r+1])
    			if(s[r+1]<=s[l])
    				r++;
    			else
    				return 0;
    		else
    			if(s[l-1]>=s[r])
    				l--;
    			else
    				return 0;
    	}
    	return 1;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("c.in","r",stdin);
    	freopen("c.out","w",stdout);
    #endif
    	int t;
    	scanf("%d",&t);
    	while(t--)
    		if(solve())
    			printf("Yes
    ");
    		else
    			printf("No
    ");
    	return 0;
    }
    
  • 相关阅读:
    【译】第33节---种子数据
    python文件的读写
    python-----实现数据库安装和连接操作
    学习进度(第三周)
    解 idea(.IntelliJIdea2019.3)双击打不开的原因
    python爬虫------处理cookie的相关请求
    安装retrying模块出现 (Retry(total=4, connect=None, read=None, redirect=None, status=None))
    java----统计疫情可视化展示--echarts(三)
    java----统计疫情可视化展示--echarts(二)
    java----统计疫情可视化展示--echarts
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8612051.html
Copyright © 2011-2022 走看看