P2804-神秘数字
题目描述(简化版)
有 n 个数,求这 n 个数中,有多少个连续的数的平均数大于某个给定的数 M?
注意:这个数可能会很大,请输出这个数对92084931取模的结果。
输入输出格式
输入格式:共两行。
第一行为两个数 n 和 M。
第二行为 n 个数。
输出格式:一行一个数,即问题的解对92084931取模的结果
输入输出样例
输入样例#1:
4 3 1 5 4 2
输出样例#1:
5
输入样例#2:
4 4 5 2 7 3
输出样例#2:
6
说明
【样例解释】
①对于这4个数,问题的解有{5},{4},{5,4},{1,5,4},{5,4,2}共5组。
②对于这4个数,问题的解有{5},{7},{2,7},{7,3},{5,2,7},{5,2,7,3}共6组。
【数据规模】
对于10%的数据,1<n≤10.
对于30%的数据,1<n≤1000.
对于50%的数据,1<n≤30000.
对于100%的数据,1<n≤200000,1<M≤3000,每个数均为正整数且不大于5000.
分析
把数列中的 n 个数字都减去 m。那么某一段的和大于0就是满足要求的一段。
于是问题就转化为:求当前数列中有多少个区间的和大于0。
很容易求出数列的前缀和,放在数组 p 中。
如果第 i 个数到第 j 个数满足要求(假定 i<j),很容易想到 p[j]-p[i-1]>0。
也就是说:p[j]>p[i-1]
问题转化为:求 p[j] 之前有多少个 p[i]>p[j],把相对于每一个p[j]的答案个数相加就是 ans
也就是求前缀和数列p的逆序对
期望复杂度O(nlogn)
程序:
100%
1 // 100% answer 2 // Merge Sort 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstdio> 6 using namespace std; 7 const int MAX = 200000 + 1; 8 int n, avg, p[MAX], a[MAX], tmp[MAX], ans; 9 int merge(int l,int mid,int r) 10 { 11 int i=l, j=mid+1, k=l-1; 12 while(i<=mid && j<=r) 13 { 14 if(p[i]<p[j]) 15 { 16 ans+=(mid-i+1); 17 ans%=92084931; 18 tmp[++k]=p[j]; 19 j++; 20 } 21 else 22 if(p[i]>=p[j]) 23 { 24 tmp[++k]=p[i]; 25 i++; 26 } 27 } 28 while(i<=mid) 29 tmp[++k]=p[i++]; 30 while(j<=r) 31 tmp[++k]=p[j++]; 32 for(int i=l;i<=r;i++) 33 p[i]=tmp[i]; 34 } 35 void MergeSort(int l, int r) 36 { 37 if (l < r) 38 { 39 int mid = (l+r) >> 1; 40 // int mid = (l+r)/2; 41 MergeSort(l,mid); 42 MergeSort(mid+1,r); 43 merge(l,mid,r); 44 } 45 } 46 int main() 47 { 48 cin >> n >> avg; 49 p[0] = 0; 50 for (int i = 1; i <= n; i++) 51 { 52 cin >> a[i]; 53 a[i] -= avg; 54 p[i] = p[i-1] + a[i]; 55 } 56 MergeSort(0,n); 57 cout << ans << endl; 58 return 0; 59 }
45%
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int MOD = 92084931; 6 int main() 7 { 8 int n,avg,a[200000],p[200000]; 9 cin >> n >> avg; 10 p[0] = 0; 11 for (int i = 1; i <= n; i++) 12 { 13 cin >> a[i]; 14 p[i] = p[i-1] + a[i]; 15 } 16 int ans = 0; 17 for (int i = 1; i <= n; i++) 18 for (int j = i; j <= n; j++) 19 { 20 if ((p[j]-p[i-1])>(avg*(j-i+1))) 21 { 22 ans++; 23 } 24 } 25 cout << ans%MOD << endl; 26 return 0; 27 }