题解子数组有主元素

Posted kcn999

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解子数组有主元素相关的知识,希望对你有一定的参考价值。

题目描述

  一个数组B,如果有其中一个元素出现的次数大于length(B) div 2,那么该元素就是数组B的主元素,显然数组B最多只有1个主元素,因为数组B有主元素,所以被称为“优美的”。

  给出数组A[0..n-1],问数组A有多少个“优美的”子数组。数组A的子数组是由数组A的连续若干个元素构成的数组。数组A不是直接给出的,而是通过如下公式自动产生的:

for i = 0 to n-1 do

{

  A[i] = (seed div 2^16) % m

  seed = (seed * 1103515245 + 12345) % 2^31

}

  如上公式中:  n, seed, m都是输入数据给出的,div是表示整数的整除。^是表示幂运算。

 

输入输出格式

输入格式

  一行,3个整数,n,  seed,  m。1 <= n <= 100000。 0 <= seed <= 2^31-1。 1 <= m <= 50。

 

输出格式

  一个整数。

 

输入输出样例

输入样例一

5  200  5

 

输出样例一

8

 

输入样例二

10  15  3

 

输出样例二

23

 

输入样例三

8  12345678  1

 

输出样例三

36

 

输入样例四

27  541  50

 

输出样例四

27 

 

题解

  观察此题,$m$很小,我们可以从这里入手。

  枚举$[0,m]$中的$i$,设$d[j]$为$[1,j]$中$a$数组内元素$i$的数量,$d[0]=0$,那么很容易想到,如果$[l,r]$有主元素,那么$d[r]-d[l-1]>0$即$d[r]>d[l-1]$。

  此时我们可以设$s[k]$为$[1,j]$中$d$数组内元素$k$的数量,用树状数组等维护一下即可,这样就可以用$O(mnlogn)$的时间复杂度通过这题了。

技术图片
#include <iostream>
#include <cstdio>
#include <cstring>

#define MAX_N (100000 + 5)

#define lowbit(x) ((x) & -(x))

using namespace std;

int n;
int a[MAX_N];

int seed, m;
const int pow2_16 = 1 << 16;
const long long pow2_32 = 1ll << 31;

int d[MAX_N];
int s[MAX_N + MAX_N];
long long ans;

int main()
{
    scanf("%d%d%d", &n, &seed, &m);
    for(register int i = 1; i <= n; ++i)
    {
        a[i] = (seed / pow2_16) % m;
        seed = (seed * 1103515245ll + 12345) % pow2_32;
    }
    for(register int i = 0; i < m; ++i)
    {
        d[0] = 0;
        memset(s, 0, sizeof s);
        for(register int j = n + 1; j <= n + n + 1; j += lowbit(j))
        {
            ++s[j];
        }
        for(register int j = 1; j <= n; ++j)
        {
            if(a[j] == i) d[j] = d[j - 1] + 1;
            else d[j] = d[j - 1] - 1; 
            for(register int k = d[j] + n; k; k -= lowbit(k))
            {
                ans += s[k];
            }
            for(register int k = d[j] + n + 1; k <= n + n + 1; k += lowbit(k))
            {
                ++s[k];
            }
        }
    }
    printf("%lld", ans);
    return 0;
}
参考程序O(mnlogn)

 

以上是关于题解子数组有主元素的主要内容,如果未能解决你的问题,请参考以下文章

Java 求解最长递增子序列

Java 求解最长递增子序列

精选力扣500题 第29题 LeetCode 53. 最大子序和c++ / java 详细题解

LeeCode 53. 最大子序和

LeetCode 152. 乘积最大子数组c++/java详细题解

817. Linked List Components - LeetCode