做题感悟:这题可以直接二分,也可以分段二分和枚举差不多。
解题思路:
存每个数的时候同时存每个数的下标,然后排个序先按从小到大排,再按下标从小到大排,这样相同的数都在一块,因为最多可以选 k 个,那么我们就按 K 个来,这样依次枚举每个数的最大范围(在同一个数的区间内),分段二分就可以了。感觉数据有点水,写完竟然 1 A .
代码:
#include<iostream> #include<sstream> #include<map> #include<cmath> #include<fstream> #include<queue> #include<vector> #include<sstream> #include<cstring> #include<cstdio> #include<stack> #include<bitset> #include<ctime> #include<string> #include<cctype> #include<iomanip> #include<algorithm> using namespace std ; #define INT long long int #define L(x) (x * 2) #define R(x) (x * 2 + 1) const int INF = 0x3f3f3f3f ; const double esp = 0.0000000001 ; const double PI = acos(-1.0) ; const int mod = 1000000007 ; const int MY = (1<<5) + 5 ; const int MX = (1<<20) + 5 ; const int S = 20 ; int n ,m ; int sum[MX] ,g[MX] ; struct node { int c ,id ; }T[MX] ; bool cmp(node a ,node b) { if(a.c == b.c) return a.id < b.id ; else return a.c < b.c ; } int main() { while(~scanf("%d%d" ,&n ,&m)) { for(int i = 1 ;i <= n ; ++i) { scanf("%d" ,&T[i].c) ; T[i].id = i ; // 位置 } sort(T ,T+n+1 ,cmp) ; memset(sum ,0 ,sizeof(sum)) ; g[0] = 0 ; g[1] = T[1].c ; for(int i = 2 ;i <= n ; ++i) { if(T[i].c == T[i-1].c) sum[i] = sum[i-1] + T[i].id - T[i-1].id -1 ; g[i] = T[i].c ; } int i = 1 ,ans = 1 ,Le ,Rt ; while(i < n) { Le = i ; Rt = upper_bound(g ,g+n+1 ,T[i].c) - g ; // 寻找同一组的边界 for(int j = Le ;j < Rt ; ++j) { int mx = upper_bound(sum+Le ,sum+Rt ,sum[j]+m) - sum ; ans = max(ans ,mx - j) ; } i = Rt ; } cout<<ans<<endl ; } return 0 ; }
原文:http://blog.csdn.net/nyist_zxp/article/details/41123589