题目描述

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

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

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

  \(n\leq 100000\)

题解

  求前缀和\(s\),约束转化为任意时刻\(s_l\geq 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\n");
else
printf("No\n");
return 0;
}

【XSY2787】Mythological VII 贪心的更多相关文章

  1. hdu5338 ZZX and Permutations(贪心、线段树)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud ZZX and Permutations Time Limit: 6000/300 ...

  2. codeforces 335A Banana(贪心)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud    Banana Piegirl is buying stickers for ...

  3. HUD 1288 Hat's Tea(反向的贪心,非常好的一道题)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1288 Hat's Tea Time Limit: 2000/1000 MS (Java/Others)  ...

  4. 【BZOJ5249】IIIDX(贪心,线段树)

    题意: 思路:赛季结束之前余总推荐的一道好题,不愧是余总 From https://www.cnblogs.com/suika/p/8748115.html 简略的说就是在预留足够多的位置的前提下贪心 ...

  5. 【CF1249F】Maximum Weight Subset(贪心)

    题意:给定一棵n个点带点权的树,要求从中选出一个点集,使得这些点两两之间距离都大于K,求最大点权和 n,K<=2e2,1<=a[i]<=1e5 思路:树形DP显然可做,极限是n方,然 ...

  6. 【CF1249D】Too Many Segments(贪心,set,vector)

    题意:给定n条线段和覆盖上限k,每条线段都覆盖了区间内的整点 问最少删掉几条线段能使所有的整点都被覆盖不超过k次 k<=n<=2e5,l[i],r[i]<=2e5 思路:比赛时候不会 ...

  7. 【CF1210B】Marcin and Training Camp(贪心)

    题意:有n个人,60种技能点,如果第i个人会第j种技能a[i]的二进制表示的第j位就是1,第i个人的价值是b[i] 如果有若干种技能i会j不会,i就会鄙视j 求一种至少两个人的选人方案使得价值和最大, ...

  8. BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]

    1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1383  Solved: 582[Submit][St ...

  9. HDOJ 1051. Wooden Sticks 贪心 结构体排序

    Wooden Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

随机推荐

  1. 2018湘潭邀请赛C题(主席树+二分)

    题目地址:https://www.icpc.camp/contests/6CP5W4knRaIRgU 比赛的时候知道这题是用主席树+二分,可是当时没有学主席树,就连有模板都不敢套,因为代码实在是太长了 ...

  2. 有界算子p129

    ? 如果我把这里的1改成2,把1/(a-b) 换成1/2(a-b) 为什么不能是? 2. 这里的x是关于t的函数,为什么x属于 结果了?和x应该没有关系呀? 3. 那为什么T的范数不是一个固定值?为什 ...

  3. alibaba druid

    FAQ · alibaba/druid Wikihttps://github.com/alibaba/druid/wiki/FAQ sql 连接数不释放 ,Druid异常:wait millis 40 ...

  4. Hibernate two table same id

    Hibernate更新数据(不用update也可以) - 森林木马 - 博客园 https://www.cnblogs.com/owenma/p/3481497.html hibernate级联更新会 ...

  5. PropertyChangeSupport 监听器模式的应用

    PropertyChangeSupport 类实现的监听器功能 ,它是java jdk自带的一个类,用于监听某个对象属性的改变来触发相应信息,具体看代码介绍 import java.beans.Pro ...

  6. [转帖]Stack的三种含义

    Stack的三种含义 http://www.ruanyifeng.com/blog/2013/11/stack.html 学习编程的时候,经常会看到stack这个词,它的中文名字叫做"栈&q ...

  7. Mysql 5.7 Windows 版本(zip)的安装简单过程

    1. 下载zip包 https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.25-winx64.zip 2. 找一个目录解压缩 3. 简单进行安装: ...

  8. [转帖]linux tree命令--显示目录的树形结构

    linux tree命令--显示目录的树形结构    版权声明:iamqilei@qq.com https://blog.csdn.net/u011729865/article/details/533 ...

  9. transform: translate(-50%, -50%) 实现块元素百分比下居中

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  10. Python 爬虫 解析库的使用 --- XPath

    一.使用XPath XPath ,全称XML Path Language,即XML路径语言,它是一门在XML文档中查找信息的语言.它最初是用来搜寻XML文档的,但是它同样适用于HTML文档的搜索. 所 ...