• 【HDU4193】Non-negative Partial Sums-单调队列


    题目大意:有一个包含N个数的数列,可以将前面的K(0≤K≤N-1)个数移到数列的后面,形成N个数列,求在这些数列当中,有多少个数列满足:对于所有的i(1≤i≤N),数列的前i个数之和为非负数。

    做法:首先,将该数列复制一份放在该数列的后面,形成一个长度为2*N的数列,用sum[i]表示该数列中前i个数的和。我们发现,对于题目中所说的,将数列前面的K个数移到数列后面所形成的数列,可以得出该数列中前i项的和为:sum[i+K]-sum[K],由于对于每个K来说,sum[K]是固定的,所以我们只需要知道在sum[K+1]到sum[K+n]中的最小值减去sum[K]是不是非负数,就可以判断这个数列符不符合条件了。于是这个问题就转化为求滚动区间的最小值的问题了,不难想到用单调队列维护的做法。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define inf 999999999
    using namespace std;
    int n;
    int sum[2000010];
    struct {int val;int pos;} q[1000010];
    
    int main()
    {
      scanf("%d",&n);
      while(n!=0)
      {
        for(int i=1;i<=n;i++)
    	{
    	  scanf("%d",&sum[i]);
    	  sum[i+n]=sum[i];
    	}
    	for(int i=2;i<=n*2;i++)
    	  sum[i]+=sum[i-1];
    	int h=0,t=0;
    	memset(q,0,sizeof(q));
    	for(int i=1;i<n;i++)
    	{
    	  while(h<t&&q[h].pos<i-n+1) h++;
    	  while(h<t&&q[t-1].val>=sum[i]) t--;
    	  q[t].val=sum[i];q[t].pos=i;t++;
    	}
    	int ans=0;
    	for(int k=1;k<=n;k++)
    	{
    	  while(h<t&&q[h].pos<k) h++;
    	  while(h<t&&q[t-1].val>=sum[n+k]) t--;
    	  q[t].val=sum[n+k];q[t].pos=n+k;t++;
    	  if (q[h].val-sum[k-1]>=0) ans++;
    	}
    	printf("%d
    ",ans);
    	scanf("%d",&n);
      }
      
      return 0;
    }
    


  • 相关阅读:
    WINREG.H 编译出错
    WINREG.H 编译出错
    JS创建对象的几种方式
    清除radio单选框外边距
    Dragging MovieClips
    Cannot Say No
    分层提高软件系统的可测试性
    如何从技术上掌控项目?
    领导我只需要你告诉我你要做什么,怎么做让我来好吗?
    如何依据框架进行任务分解
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793948.html
Copyright © 2020-2023  润新知