题意:给你一个串,问满足以下条件的子串中最长的是多长:对于每个数字,要么在这个子串没出现过,要么出现次数超过k次。

思路:对于这类问题,常常转化为数据结构的询问问题。我们考虑枚举右端点,对于当前右端点,我们单独考虑每一种数的合法区间。假设当前枚举的右端点是i,考虑的数字是c,在右端点左边离i最近的数字c的位置是p1,离i第k远的数字c的位置是p2, 容易发现,数字c的合法区间为[1, p2]和[p1 + 1, i],对应的情况是选择这个数至少k个和不选这个数。那么,如果我们用线段树来维护覆盖的区间,对于每一种数的合法区间在线段树上+1,这样我们只要找到在i前面值为c的最小的位置就是右端点为i的最优解。由于每次右端点只移动1,所以可以在O(logn)时间内维护一个数合法区间的变化。最小位置的找法可以通过维护区间最大值然后在线段树上二分即可。

代码:

#include <bits/stdc++.h>
#define ls (o << 1)
#define rs (o << 1 | 1)
using namespace std;
const int maxn = 100010;
vector<int> pos[maxn];
int now[maxn];
int n, c, k;
int a[maxn];
struct SegmenTree {
int mx, lz;
};
SegmenTree tr[maxn * 4];
void pushup(int o) {
tr[o].mx = max(tr[ls].mx, tr[rs].mx);
}
void pushdown(int o) {
if(tr[o].lz != 0) {
tr[ls].mx += tr[o].lz;
tr[rs].mx += tr[o].lz;
tr[ls].lz += tr[o].lz;
tr[rs].lz += tr[o].lz;
tr[o].lz = 0;
}
}
void build(int o, int l, int r) {
tr[o].mx = 0;
tr[o].lz = 0;
if(l == r) {
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
pushup(o);
}
void update(int o, int l, int r, int ql, int qr, int val) {
if(ql > qr) return;
if(l >= ql && r <= qr) {
tr[o].lz += val;
tr[o].mx += val;
return;
}
pushdown(o);
int mid = (l + r) >> 1;
if(ql <= mid) update(ls, l, mid, ql, qr, val);
if(qr > mid) update(rs, mid + 1, r, ql, qr, val);
pushup(o);
}
int query(int o, int l, int r) {
if(l == r) return l;
int ans = -1, mid = (l + r) >> 1;
pushdown(o);
if(tr[ls].mx == c) ans = query(ls, l, mid);
else if(tr[rs].mx == c) ans = query(rs, mid + 1, r);
return ans;
}
int main() {
while(~scanf("%d%d%d", &n, &c, &k)) {
for (int i = 1; i <= c; i++) {
pos[i].clear();
pos[i].push_back(0);
}
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
pos[a[i]].push_back(i);
}
build(1, 1, n);
for (int i = 1; i <= c; i++) {
pos[i].push_back(n + 1);
update(1, 1, n, pos[i][0] + 1, pos[i][1] - 1, 1);
now[i] = 0;
}
int ans = 0;
for (int i = 1; i <= n; i++) {
int t = a[i];
update(1, 1, n, pos[t][now[t]] + 1, pos[t][now[t] + 1] - 1, -1);
if(now[t] >= k) update(1, 1, n, 1, pos[t][now[t] - k + 1], -1);
now[t]++;
update(1, 1, n, pos[t][now[t]] + 1, pos[t][now[t] + 1] - 1, 1);
if(now[t] >= k) update(1, 1, n, 1, pos[t][now[t] - k + 1], 1);
int tmp = query(1, 1, n);
if(tmp != -1)
ans = max(ans, i - tmp + 1);
}
printf("%d\n", ans);
}
}

  

2019HDU多校训练第二场 Longest Subarray的更多相关文章

  1. CSU 多校训练第二场 J Pinemi Puzzles

    传送门:http://acm.csu.edu.cn:20080/csuoj/problemset/problem?pid=2279 题意: 代码: #include <set> #incl ...

  2. 2015多校训练第二场 hdu5305

    把这题想复杂了,一直在考虑怎么快速的判断将选的边和已选的边无冲突,后来经人提醒发现这根本没必要,反正数据也不大开两个数组爆搜就OK了,搜索之前要先排除两种没必要搜的情况,这很容易想到,爆搜的时候注意几 ...

  3. 18牛客多校训练第二场 J farm

    题意:一个n×m的农田, 每个小格子都有一种作物, 现在喷t次农药,每次农药覆盖一个矩形, 该矩形里面与农药类型不同的植物都会死掉, 求最后植物的死亡数是多少. 题解:二维树状数组. 每次喷农药的时候 ...

  4. 2019HDU多校赛第二场 H HDU 6598 Harmonious Army(最小割模型)

    参考博客https://blog.csdn.net/u013534123/article/details/97142191 #include<bits/stdc++.h> using na ...

  5. 牛客网多校训练第二场D Kth Minimum Clique

    链接:https://ac.nowcoder.com/acm/contest/882/D来源:牛客网 Given a vertex-weighted graph with N vertices, fi ...

  6. HDU6578 2019HDU多校训练赛第一场 1001 (dp)

    HDU6578 2019HDU多校训练赛第一场 1001 (dp) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题意: 你有n个空需要去填,有 ...

  7. HDU6579 2019HDU多校训练赛第一场1002 (线性基)

    HDU6579 2019HDU多校训练赛第一场1002 (线性基) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6579 题意: 两种操作 1.在序列末 ...

  8. 可持久化线段树的学习(区间第k大和查询历史版本的数据)(杭电多校赛第二场1011)

    以前我们学习了线段树可以知道,线段树的每一个节点都储存的是一段区间,所以线段树可以做简单的区间查询,更改等简单的操作. 而后面再做有些题目,就可能会碰到一种回退的操作.这里的回退是指回到未做各种操作之 ...

  9. 2018牛客暑期ACM多校训练营第二场(有坑未填)

    第二场终于等来学弟 开始(被队友带飞)的开心(被虐)多校之旅 A   run A题是一个递推(dp?)+前缀和 因为看数据量比较大 就直接上前缀和了 一个比较简单的递推 没有太多难点 签到题 需要注意 ...

随机推荐

  1. vue 字符串长度控制显示的字数超出显示省略号

    1. html <p class="index__Feature-list-itemlist-title newline"> {{item.name| ellipsis ...

  2. bzoj4244 & loj2878. 「JOISC 2014 Day2」邮戳拉力赛 括号序列+背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4244 https://loj.ac/problem/2878 题解 挺妙的一道题. 一开始一直 ...

  3. grep正则表达式(二)

    任意字符(The Any Character) dot or period character: "." grep -h '.zip' dirlist*.txt ".&q ...

  4. 转载:Eclipse下的java工程目录

    原文链接:https://www.cnblogs.com/milantgh/p/4029003.html 对新手来讲,一个Java工程内部的多个文件夹经常会让大家困惑.更可恶的是莫名其妙的路径问题,在 ...

  5. Sublime Text 快捷键汇总

    1. 常用快捷键 Ctrl+D 选词 (反复按快捷键,即可继续向下同时选中下一个相同的文本进行同时编辑)Ctrl+G 跳转到相应的行Ctrl+J 合并行(已选择需要合并的多行时)Ctrl+L 选择整行 ...

  6. 【HDOJ6599】I Love Palindrome String(PAM,manacher)

    题意:给出一个由小写字母组成的长为n的字符串S,定义他的子串[L,R]为周驿东串当且仅当[L,R]为回文串且[L,(L+R)/2]为回文串 求i=[1,n] 所有长度为i的周驿东串的个数 n<= ...

  7. HDU 3183 A Magic Lamp(RMQ问题, ST算法)

    原题目 A Magic Lamp Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  8. Java 时间相关

    java的时间主要关注这几个类,查看Java API 1.6 java.util.Calendar Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR.MONTH.DAY_OF_MON ...

  9. 启动项目时出现Error: Node Sass does not yet support your current environment: Windows 64-bit with Unsupported runtime (72)

    前几天趁假期重新装了一次系统,重新安装各种配置之后再启动项目的时候就报这个错误 第一反应就是去搜这个错误怎么解决,搜来搜去基本上都是让我重新安装node-sass,但我重装node-sass的时候又出 ...

  10. python+selenium+chromewebdriver或Firefox的环境搭建

    插件下载地址 chromewebdriver:https://chromedriver.storage.googleapis.com/index.html?path=2.26/放置在python下的S ...