校内模拟赛(二)(9)

时间:2019-09-18
本文章向大家介绍校内模拟赛(二)(9),主要包括校内模拟赛(二)(9)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题1:非负的部分和 
【题目描述】 
  WZK最近收到了一个任务。 
给出一个 n 个数的序列,为 A0,A1,,,,An-1,循环移动 k 位之后,这
成了 Ak,Ak+1,,,,An-1,A0,A1,,,,Ak-1。一种优秀的循环移动是,
前i(1<=i<=n)项和都满足不小于零。请给出这个序列优秀循环移动的个数。 
  这道题目当然是很简单啦,但是 WZK忙着吃小浣熊干脆面,手上油油的写不
是就麻烦你啦!如果能做到满分,他就会考虑请你吃一包哦~ 
 
【输入格式】 
  第一行一个整数 n(1 <= n <= 10^6),表示有n个数。 
  第二行n个整数,Ai(-1000 <= Ai <= 1000)表示给出的第i 个数。 
 
【输出格式】 
  一行一个整数,表示优秀循环移动的个数。 
 
【样例输入】 
3 
2 2 1 
 
【样例输出】 
View Code

很神奇的题,直接单调队列维护就好了

手推很容易出公式的,qwq

#include<bits/stdc++.h>
#define I inline
using namespace std;
const int N=1e6+7;
int a[N],s[N*2],n,ans;
deque<int> que;
I int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main()
{
    freopen("sum.in","r",stdin);
    freopen("sum.out","w",stdout);
    n=read();
    for (int i=1;i<=n;i++)
    s[i]=s[i-1]+read(),s[i+n]=s[i];
    for (int i=n+1;i<=2*n;i++) s[i]+=s[n];
    que.push_back(1);
    for (int i=1;i<n;i++)
    {
        while (!que.empty()&&s[que.back()]>s[i]) que.pop_back();
        que.push_back(i);
    }
    for (int i=n;i<2*n;i++)
    {
        if (que.front()<=i-n) que.pop_front();
        while (!que.empty()&&s[que.back()]>s[i]) que.pop_back();
        que.push_back(i);
        if (s[que.front()]-s[i-n]>=0) ans++;
    }
    printf("%d\n",ans);
    return 0;
}
View Code

原文地址:https://www.cnblogs.com/Hale522520/p/11541214.html