zoukankan      html  css  js  c++  java
  • [2019牛客多校第三场][G. Removing Stones]

    题目链接:https://ac.nowcoder.com/acm/contest/883/G

    题目大意:有(n)堆石头,每堆有(a_i)个,每次可以选其中两堆非零的石堆,各取走一个石子,当所有石堆的石子数均为(0)时获胜。问有多少个区间([l,r])可以保证获胜(若区间内石子数总和为奇数则会选一堆石子数最小的石堆取走一个石头)。

    题解:显然,对其中的一个区间,如果区间内的最大值(mx)不超过其总和(sum)的一半,则能保证获胜。于是可以考虑每一个(a_i)作为最大值的区间([l_i,r_i]),在答案中减去其中不满足要求的区间即可,注意这个区间一定要包含(i)。

       每次枚举(i)时,先二分出最左边的(l)使得区间([l,i])恰好不满足条件,然后再二分出最左边的(r)使得([l,r])恰好不满足条件,每次将(l)加一直至达到当前的(i)即可

       时间复杂度为O(能过),求大佬帮忙分析复杂度orz

    #include<bits/stdc++.h>
    using namespace std;
    #define N 300001
    #define LL long long
    LL T,n,a[N],l[N],r[N],s[N],f[N],ans;
    void rua(LL cur,LL L,LL R)
    {
        LL l,r;
        l=upper_bound(s+L-1,s+cur+1,s[cur-1]-a[cur])-s;l++;
        r=cur;
        while(l<=cur)
          {
          r=min(R,(LL)(lower_bound(s+r+1,s+R+1,2ll*a[cur]+s[l-1])-s-1));
          ans-=r-max(cur,max(f[l]+1,l))+1;
          f[l]=max(f[l],r);
          l++;
          }
    }
    void init()
    {
        scanf("%lld",&n);
        for(LL i=1;i<=n;i++)
          scanf("%lld",&a[i]),s[i]=s[i-1]+a[i],f[i]=i;
        l[1]=1,r[n]=n;
        for(LL i=2;i<=n;i++)
          {
          LL _=i;
          while(_>1 && a[i]>=a[_-1])
            _=l[_-1];
          l[i]=_;
          }
        for(LL i=n-1;i>=1;i--)
          {
          LL _=i;
          while(_<n && a[i]>a[_+1])
            _=r[_+1];
          r[i]=_;
          }
        ans=n*(n-1)/2;
        for(LL i=1;i<=n;i++)
          rua(i,l[i],r[i]);
        printf("%lld
    ",ans);
    }
    int main()
    {
        //freopen("test.in","r",stdin);
        scanf("%lld",&T);
        while(T--)init();
        return 0;
    }
    View Code
  • 相关阅读:
    idea中pom.xml相关操作
    Java集合1-集合与数组的区别
    idea中各种图标的含义
    testng之多线程执行(并发执行)
    testng之DataProvider参数化
    fastjson将java对象与json字符串相互转换
    testng -依赖测试
    testng- 异常测试
    转-selenium3 webdriver启动火狐、chrome、edge、Safari浏览器的方法
    浏览器兼容性测试
  • 原文地址:https://www.cnblogs.com/DeaphetS/p/11245448.html
Copyright © 2011-2022 走看看