1. 程式人生 > >acd - 1427 - Nice Sequence(線段樹)

acd - 1427 - Nice Sequence(線段樹)

eof [0 條件 class 最小值 cstring info div pre

題意:一個由n個數組成的序列(序列元素的範圍是[0, n])。求最長前綴 j 。使得在這個前綴 j 中對於隨意的數 i1 < i2。都滿足隨意的 m <= j。i1 在前 m 個數裏出現的次數 >= i2 在前 m 個數裏出現的次數 - k (1 ≤ n ≤ 200 000, 0 ≤ k ≤ 200 000)。

題目鏈接:http://acdream.info/problem?pid=1427

——>>第一個前綴 j 不滿足。那麽後面的前綴一定不滿足(由於前綴 j 不滿足)。

所以,從左往右掃描,每次取全部數字 i 的最少出現次數與當前掃描到的數出現的次數比較看是否滿足條件就可以。

全部數字 i 指的是哪些數字呢?是已經出現過的數嗎?例子2說明不是。。是不大於當前出現過的最大整數嗎?WA告訴我不是。

。而是 <= a[j] 的全部非負整數。

全部數字 i 出現次數的最小值。我想到了RMQ和線段樹,最後選了線段樹來維護這個最小值。

#include <cstdio>
#include <cstring>
#include <algorithm>

#define lc (o << 1)
#define rc ((o << 1) | 1)

using std::min;
using std::max;

const int MAXN = 200000 + 10;
const int INF = 0x3f3f3f3f;

int n, k, Max;
int minv[MAXN << 2], cnt[MAXN];
int a[MAXN];

void Read()
{
    Max = -1;
    for (int i = 1; i <= n; ++i)
    {
        scanf("%d", a + i);
        ++a[i];
        if (a[i] > Max)
        {
            Max = a[i];
        }
    }
}

void Build(int o, int L, int R)
{
    minv[o] = 0;
    if (L == R) return;
    int M = (L + R) >> 1;
    Build(lc, L, M);
    Build(rc, M + 1, R);
}

void Update(int o, int L, int R, int q)
{
    if (L == R)
    {
        minv[o] = cnt[q];
        return;
    }
    int M = (L + R) >> 1;
    if (q <= M) Update(lc, L, M, q);
    else Update(rc, M + 1, R, q);
    minv[o] = min(minv[lc], minv[rc]);
}

int Query(int o, int L, int R, int ql, int qr)
{
    if (ql <= L && R <= qr)
    {
        return minv[o];
    }
    int ret = INF;
    int M = (L + R) >> 1;
    if (ql <= M) ret = min(ret, Query(lc, L, M, ql, qr));
    if (qr > M) ret= min(ret, Query(rc, M + 1, R, ql, qr));

    return ret;
}

void Solve()
{
    int i;

    memset(cnt, 0, sizeof(cnt));
    for (i = 1; i <= n; ++i)
    {
        ++cnt[a[i]];
        Update(1, 1, Max, a[i]);
        if (Query(1, 1, Max, 1, a[i]) < cnt[a[i]] - k) break;
    }
    printf("%d\n", i - 1);
}

int main()
{
    while (scanf("%d%d", &n, &k) == 2)
    {
        Read();
        Build(1, 1, Max);
        Solve();
    }

    return 0;
}


acd - 1427 - Nice Sequence(線段樹)