[2019 cattle off more school third] [G. Removing Stones]

Topic links: https://ac.nowcoder.com/acm/contest/883/G

Title effect: YES \ (n-\) stones stack, each stack has \ (a_i \) a, wherein each may be selected from a non-zero heap piles, each removal of a stone, when the number of rubble stones are all \ win when (0 \). I asked how many intervals \ ([l, r] \) ensures that the winning (removal of a number of stone pebbles interval if the sum is odd will be selected from the pile of the smallest number of rubble stones).

Solution: Obviously, for a range of them, if the maximum value \ (mx \) in the interval does not exceed the sum of \ (sum \) half, is able to guarantee wins. May then consider each \ (a_i \) as the interval maximum value of \ ([l_i, r_i] \), wherein the subtracting section can not meet the requirement of the answer, the interval must be noted that this comprises \ (I \) .

   Each enumeration \ (I \), the first two separated leftmost \ (L \) such that the interval \ ([l, i] \) just condition is not satisfied, then separate the two leftmost \ (R & lt \) such that \ ([l, r] \) is not satisfied exactly, each time \ (L \) has been added to reach the current \ (I \) to

   The time complexity is O (excessive energy), seeking help analyze the complexity of big brother 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\n",ans);
}
int main()
{
    //freopen("test.in","r",stdin);
    scanf("%lld",&T);
    while(T--)init();
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/DeaphetS/p/11245448.html