牛客练习赛3 E - 绝对半径2051
链接:https://www.nowcoder.net/acm/contest/13/E
来源:牛客网
题目描述
𝑅𝑒𝑘𝑖是一名狙击手,凭借肉眼视觉可以做到精确命中绝对半径2051公尺的一切目标。
作为一名优秀的狙击手,𝑅𝑒𝑘𝑖不仅经常保养枪支,也经常保养弹药。
𝑅𝑒𝑘𝑖有𝑛枚子弹,第𝑖枚的型号为𝐶𝑖,𝑅𝑒𝑘𝑖打算扔掉其中最多𝑘枚。
大多数优秀的狙击手都有艺术癖好,𝑅𝑒𝑘𝑖希望扔掉一部分子弹后,最
长的连续相同子弹序列的长度尽量长。
作为一名优秀的狙击手,𝑅𝑒𝑘𝑖不仅经常保养枪支,也经常保养弹药。
𝑅𝑒𝑘𝑖有𝑛枚子弹,第𝑖枚的型号为𝐶𝑖,𝑅𝑒𝑘𝑖打算扔掉其中最多𝑘枚。
大多数优秀的狙击手都有艺术癖好,𝑅𝑒𝑘𝑖希望扔掉一部分子弹后,最
长的连续相同子弹序列的长度尽量长。
输入描述:
第一行,两个整数𝑛,𝑘。𝑖
第二行,𝑛个正整数𝐶
。
输出描述:
一行,一个整数,最长的连续相同子弹序列的长度。
示例1
输入
8 1 1 1 1 2 2 3 2 2
输出
4
备注
对于10%的数据,𝑛 ≤ 10。
对于30%的数据,𝑛 ≤ 1000。
对于60%的数据,𝐶𝑖 ≤ 30。
对于100%的数据,0 ≤ 𝑘 ≤ 𝑛 ≤ 10^5,1 ≤ 𝐶𝑖 ≤ 10^9。
题解
每一种数字分开考虑,每个枚举答案以哪个位置为结尾,二分一下起点就可以了。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int a[maxn], b[maxn]; int n, k; vector<int> g[maxn]; int lsh(int x) { int L = 1, R = n; while(L <= R) { int mid = (L + R) / 2; if(b[mid] > x) R = mid - 1; else if(b[mid] < x) L = mid + 1; else return mid; } return 0; } int main() { scanf("%d%d", &n, &k); for(int i = 1; i <= n; i ++) { scanf("%d", &a[i]); b[i] = a[i]; } sort(b + 1, b + 1 + n); for(int i = 1; i <= n; i ++) { a[i] = lsh(a[i]); } for(int i = 1; i <= n; i ++) { g[a[i]].push_back(i); } int ans = 1; for(int i = 1; i <= n; i ++) { if(g[i].size() <= 1) continue; for(int j = 1; j < g[i].size(); j ++) { int L = 0, R = j, p = j; while(L <= R) { int mid = (L + R) / 2; if((g[i][j] - g[i][mid] + 1) - (j - mid + 1) <= k) { p = mid; R = mid - 1; } else { L = mid + 1; } } ans = max(ans, j - p + 1); } } printf("%d\n", ans); return 0; }