1 条题解
-
0
自动搬运
来自洛谷,原作者为

LSA
AFO||ds和数数学不会搬运于
2025-08-24 23:03:28,当前版本为作者最后更新于2024-08-30 21:42:31,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
Solution
这题明明可以做到线性怎么包括官解都写的树状数组qwq。
首先,由于选择的区间是连续的一段,而且对于每个左端点 ,其对应满足权值超过 的最小的右端点 是显然单调的,所以考虑双指针,到这里根官方题解是一样的。
接下来考虑每次移动指针怎么更新权值。
记 为当前每个颜色出现的次数, 为 的 的个数,就是颜色出现次数超过 的颜色个数。
由于双指针移动时 只会变化 ,所以这两个数组是很容易维护的。
每次 向右扩展时(这里的 还没更新),对于 的颜色 是没有影响的,因为它们的 不变;而对于 的颜色 ,由于 ,所以权值会增加 。 的扩展是同理的。
时间复杂度 。
代码实现中是先更新 再更新权值的,跟上面的描述有点区别。
#include<bits/stdc++.h> #define ll long long using namespace std; ll read(){ ll X = 0 ,r = 1; char ch = getchar(); while(!isdigit(ch) && ch != '-') ch = getchar(); if(ch == '-') r = -1,ch = getchar(); while(isdigit(ch)) X = X*10+ch-'0',ch = getchar(); return X*r; } const int N = 2e6+10; int n,a[N],m; int cnt[N],sz[N]; ll k; int main(){ n = read(); k = read(); for(int i=1;i<=n;i++) a[i] = read(); int ans = n+1; ll res = 0; for(int l=1,r=0;l<=n;l++){ while(r < n && res < k){ r++; sz[a[r]]++; cnt[sz[a[r]]]++; res += cnt[sz[a[r]]]-1; } if(res >= k) ans = min(ans,r-l+1); res -= cnt[sz[a[l]]]-1; cnt[sz[a[l]]]--; sz[a[l]]--; } printf("%d",ans == n+1 ? -1 : ans); return 0; }
- 1
信息
- ID
- 10504
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者