牛客练习赛3 绝对半径 ——k尺取法

题目

链接

题意:一个n个数字的序列,最多去掉其中k个,使得连续相同数字序列的长度尽量长

分析

如果不考虑去掉元素,就是普通的尺取。考虑到去元素,则只需做一点修改。

先离散化,再把每种元素的位置用vactor存下来。尺取的时间复杂度只有 $O(n)$,但是离散化之前需要排序,就成了 $O(n log n)$.

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
int n, k, c[maxn], rawc[maxn];
vector<int>v[maxn];

int main()
{
    scanf("%d%d", &n, &k);
    for(int i = 0;i < n;i++)
    {
        scanf("%d", &c[i]);
        rawc[i] = c[i];  //保留下原始数组
    }
    sort(c, c+n);
    int cnt = unique(c, c+n) - c;

//for(int i = 0;i < n;i++)  printf("c[%d]: %d
", i, c[i]);

    for(int i = 0;i < n;i++)
    {
        int index = lower_bound(c, c+cnt, rawc[i]) - c;
        v[index].push_back(i);
    }

    int ans = 1;
    int kk = k;  //k会变,需要保存
    for(int i = 0;i < cnt;i++)
    {
        int l = 0, r = 0;
        k = kk;
        while(l <= r && r < v[i].size() - 1)
        {
            if(k >= v[i][r+1] - v[i][r] - 1)
            {
                k -=  v[i][r+1] - v[i][r] - 1;
                r++;
            }
            else
            {
                l++;
                k += v[i][l] - v[i][l-1] - 1;
            }
            //printf("i:%d  l:%d  r:%d k:%d
", i, l, r, k);
            ans = max(ans, r-l+1);
        }
    }
    printf("%d
", ans);
    return 0;
}

参考链接:https://ac.nowcoder.com/discuss/172020

原文地址:https://www.cnblogs.com/lfri/p/11190815.html