列表

详情


NC217416. 连续非空子序列

描述

有一天,你路过机房,发现有两个人在讨论
溪染:喂,叁秋,你知道什么是连续非空子序列嘛?
叁秋:知道啊!
溪染:举个栗子?
叁秋:如果这里有个数组,那么它的连续非空子序列有
(这里定义的连续非空子序列是指数组中连续的一段,所以不包括这种不连续的
溪染:那我这里有一个数组数组里的每一个数都在范围内,共个数,编号a_1 a_2 ...a_n,你能求出它有多少个连续非空子序列满足序列内数字和大于吗?
叁秋:这不有手就行嘛,我直接暴力枚举连续非空子序列的左右范围,再暴力统计一遍不就可以了嘛!
溪染:如果我告诉你这个数组里面有个数呢?
叁秋:啊,这?
叁秋:喂!那个偷听的!我早就发现你了!帮我解决这个问题,我就不计较了你偷听我们的谈话了。

简化题意:给定一个数 , 再给出长度为  的数列 ,求有多少连续非空子序列使得序列中的数之和大于

输入描述

第一行输入一个正整数,表示数组的大小。
第二行输入,个数,表示数组中的个数。

输出描述

仅一行,表示问题的答案,即输入的数组有多少个连续非空子序列满足序列内数字和大于

示例1

输入:

5
9 -6 -5 4 8

输出:

9

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

pypy3 解法, 执行用时: 1399ms, 内存消耗: 175884K, 提交时间: 2021-06-19 13:39:10

def lowbit(x):
    return x & -x


def add(k, x):
    i = k
    while i <= n:
        tr[i] += x
        i += lowbit(i)


def query(x):
    s = 0
    i = x
    while i:
        s += tr[i]
        i -= lowbit(i)
    return s


def get(x):
    l, r = 0, len(temp) - 1
    while l < r:
        mid = l + r >> 1
        if temp[mid] >= x:
            r = mid
        else:
            l = mid + 1 
    return l + 1


n = int(input())
arr = [0]
arr.extend(list(map(int, input().split())))
tr = [0] * (n + 5)
n+=1
for i in range(1, n ):
    arr[i] += arr[i - 1]
temp = list(set(arr))
temp.sort()

res = 0

for i in range(0, n):
    k = get(arr[i]) 
    res += query(k- 1)
#     print(k, res)
    add(k, 1)
print(res)

C++ 解法, 执行用时: 510ms, 内存消耗: 15992K, 提交时间: 2021-06-19 16:30:19

#include<iostream>
using namespace std;

const int N=1e6+5;
typedef long long LL;
LL h[N],ans,t[N];
int n,a;

void nxd(int l,int r)
{
    if(l>=r) return;
    int mid=l+r>>1;
    nxd(l,mid),nxd(mid+1,r);
    int i=l,j=mid+1,k=0;
    while(i<=mid&&j<=r)
    {
        if(h[i]>=h[j]) t[k++]=h[j++];
        else ans+=r-j+1,t[k++]=h[i++];
    }
    while(i<=mid) t[k++]=h[i++];
    while(j<=r) t[k++]=h[j++];
    for(j=0,i=l;i<=r;i++,j++) h[i]=t[j];
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
     cin>>a,h[i]=h[i-1]+a;
    nxd(0,n);
    cout<<ans;
    return 0;
}

上一题