洛谷 P2309 loidc,卖卖萌

题目背景

Loidc萌萌哒。

他最近一直在靠卖萌追求他的真爱——vivym,经过几轮攻势后vivym酱眼看就要被他所攻略。擅长数据结构的vivym决定利用强大的数据结构之力帮助自己逃脱。

题目描述

Vivym给了loidc一串阿拉伯数字。他将一个数串的每个数字之和定义为该数串的数串和,vivym要求loidc求出数字中有多少个子串的数串和为正数。他想了半天总是解决不好,于是他便将这一棘手的问题交给了编程能力极强的你,他希望你能在1s内解决。不然vivym就要闪现过墙幽灵疾步跑掉了

输入输出格式

输入格式:

 

第一行一个数n,表示数串的长度。

第二行一共n个数,它就是那串阿拉伯数字

 

输出格式:

 

一个数,表示铭文中有多少个子串的数串和为正数。

 

输入输出样例

输入样例#1: 复制
3
8 -9 2
输出样例#1: 复制
3

说明

30% n<=1000。

100% n<=100000。

对于题目读入的其他变量均介于-100~100。

思路:前置和+逆序对。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
long long ans; 
long long num[100010],sum[100010],tmp[100010];
void up(int l,int mid,int r){
    int i=l,j=mid+1,tot=0;
    while(i<=mid&&j<=r){
        if(num[i]>num[j])    ans+=mid-i+1;
        tmp[++tot]=num[i]<=num[j]?num[i++]:num[j++];
    }
    while(i<=mid)    tmp[++tot]=num[i++];
    while(j<=r)    tmp[++tot]=num[j++];
    for(int k=1;k<=tot;k++)
        num[l++]=tmp[k];
}
void work(int l,int r){
    if(l<r){
        int mid=(l+r)/2;
        work(l,mid);
        work(mid+1,r);
        up(l,mid,r);
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&num[i]);
        sum[i]=sum[i-1]+num[i];
    }
    for(int i=1;i<=n;i++){ 
        num[i]=sum[n-i+1];
        if(num[i]>0)    ans++;
    } 
    work(1,n);
    cout<<ans;
}

 

posted @ 2017-12-06 21:42  一蓑烟雨任生平  阅读(182)  评论(0编辑  收藏  举报