zoukankan      html  css  js  c++  java
  • LG-P2804 神秘数字/LG-P1196 火柴排队 归并排序, 逆序对

    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 }
    View Code

     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 }
    View Code
  • 相关阅读:
    【转】由浅入深表达式树(一)创建表达式
    【转】背后的故事之
    【转】背后的故事之
    【转】C#集合类型大盘点
    【转】最近用Timer踩了一个坑,分享一下避免别人继续踩
    【转】《深入理解C# 3.x的新特性》博文系列汇总
    【转】文件各种上传,离不开的表单
    【转】文件下载之断点续传(客户端与服务端的实现)
    【转】权限管理学习 一、ASP.NET Forms身份认证
    【转】C#单元测试,带你快速入门
  • 原文地址:https://www.cnblogs.com/OIerPrime/p/7966649.html
Copyright © 2011-2022 走看看