zoukankan      html  css  js  c++  java
  • 100200F Think Positive

    传送门

    题目大意

    给你一个数n和长度为n的序列,序列中的每个数均为1或-1,如果一个点j对于任意的k都满足题目中给的式子,则j是一个合法位置,问这样的j有多少个

    分析

    这道题有两种方法,分别对应代码1和代码2。

    方法1

    我们发现最终答案实际就是这n个数的和与0去最大值,因为我们不难发现对于任意两个相邻的1和-1它们的存在是没有意义的,因为这两个位置肯定不合法,而它们的和为0,对其它位置没有影响。所以在得到这些后我们只需把相邻的1和-1不断删掉就行了,因此可以证明之前的猜想。

    方法2

    我们发现对于每个j对应的最坏情况的k只有图1和图2两种情况,所以只要这两种情况满足且j的后缀大于0这个j就是合法的。

    图1图2

    这里的maxsur和minpre都是对于k的取值范围内的min或max,这就不由让我们想起了单调队列。我们根据sur和pre各建一个单调队列,然后用数组记录某个点是否两种情况均满足就可以了,注意在计算时的顺序问题,详见代码。

    代码1

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
          freopen("positive.in","r",stdin);
          freopen("positive.out","w",stdout);
          int n,i,ans=0;
          cin>>n;
          for(i=1;i<=n;i++){
            int x;
              cin>>x;
              ans+=x;
          }
          if(ans>=0)cout<<ans<<endl;
              else cout<<0<<endl;
          return 0;
    }

    代码2

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    int pre[200100],sur[200100],qp[200100],qs[200100],lp,rp,ls,rs,a[200100];
    int p1[200100],p2[200100],is[200100];
    inline void init(){
          memset(pre,0,sizeof(pre));
          memset(sur,0,sizeof(sur));
          memset(qp,0,sizeof(qp));
          memset(qs,0,sizeof(qs));
          memset(is,0,sizeof(is));
          lp=ls=1;
          rp=rs=0;
    }
    int main(){
          freopen("positive.in","r",stdin);
          freopen("positive.out","w",stdout);
          int n,i,ans=0;
          init();
          scanf("%d",&n);
          for(i=1;i<=n;i++){
              scanf("%d",&a[i]);
              pre[i]=pre[i-1]+a[i];
          }
          for(i=n;i>0;i--)sur[i]=sur[i+1]+a[i];
          for(i=n;i>0;i--){
              while(pre[i]<qp[rp]&&rp>0){
                rp--;
              }
              qp[++rp]=pre[i];
              p1[rp]=i;
          }
          for(i=1;i<=n;i++){
              while(sur[i]>qs[rs]&&rs>0){
                rs--;
              }
              qs[++rs]=sur[i];
              p2[rs]=i;
          }
          for(i=1;i<=n;i++){
              while(p2[ls]<=i&&ls<=rs)ls++;
              if(ls>rs){
                if(sur[i]>0)is[i]++;
                continue;
              }
              if(sur[i]-qs[ls]>0)is[i]++;
          }
          for(i=n;i>0;i--){
              while(p1[lp]>=i&&lp<=rp)lp++;
              if(lp>rp){
                if(sur[i]>0)is[i]++;
                continue;
              }
              if(sur[i]+qp[lp]>0)is[i]++;
          }
          for(i=1;i<=n;i++)
            if(sur[i]>0&&is[i]==2)
              ans++;
          cout<<ans<<endl;
          return 0;
    }
  • 相关阅读:
    Python 线程池,进程池,协程,和其他
    python 类的特殊成员方法
    Python 进程,线程,协程
    Python Socket第二篇(socketserver)
    Python 面向对象
    Python Socket
    saltstack 基础
    Python 面向对象学习
    Python 常用模块
    日志滚动工具
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9399967.html
Copyright © 2011-2022 走看看