题目背景
Loidc萌萌哒。
他最近一直在靠卖萌追求他的真爱——vivym,经过几轮攻势后vivym酱眼看就要被他所攻略。擅长数据结构的vivym决定利用强大的数据结构之力帮助自己逃脱。
题目描述
Vivym给了loidc一串阿拉伯数字。他将一个数串的每个数字之和定义为该数串的数串和,vivym要求loidc求出数字中有多少个子串的数串和为正数。他想了半天总是解决不好,于是他便将这一棘手的问题交给了编程能力极强的你,他希望你能在1s内解决。不然vivym就要闪现过墙幽灵疾步跑掉了
输入输出格式
输入格式:
第一行一个数n,表示数串的长度。
第二行一共n个数,它就是那串阿拉伯数字
输出格式:
一个数,表示铭文中有多少个子串的数串和为正数。
输入输出样例
说明
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; }