题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6602

题目大意为求最长的区间,满足C种数字在区间内要么不出现,要么出现的次数都不小于K。

大致的分析一下,可以知道对于以R为右端点的区间来说,每种颜色的合法区间在[1~出现k次]和(上一次出现~下一次出现)。PS:[]为闭区间,()为开区间。

所以可以线段树维护一下,枚举区间右端点,然后在线段树上将上一次更新这种颜色的操作撤销(上次是+1,则当前-1),然后再次更新(+1)。

对于每个区间右端点,最大的有效区间为线段树上种类为C的最左边的位置。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#define lson l,mid,i<<1
#define rson mid+1,r,i<<1|1
using namespace std;
typedef long long ll;
const int maxn = 2e5 + ;
const ll mod = ;
int Max[maxn * ], lazy[maxn * ];
vector<int>cnt[maxn];
int num[maxn];
int n, c, k;
void up(int i) {
Max[i] = max(Max[i << ], Max[i << | ]);
}
void down(int i) {
if (lazy[i]) {
lazy[i << ] += lazy[i];
lazy[i << | ] += lazy[i];
Max[i << | ] += lazy[i];
Max[i << ] += lazy[i];
lazy[i] = ;
}
}
void build(int l, int r, int i) {
Max[i] = lazy[i] = ;
if (l == r)
return;
int mid = l + r >> ;
build(lson);
build(rson);
up(i);
}
void update(int L, int R, int k, int l, int r, int i) {
if (L > R)return;
if (L <= l && r <= R) {
Max[i] += k;
lazy[i] += k;
return;
}
down(i);
int mid = l + r >> ;
if (L <= mid)update(L, R, k, lson);
if (R > mid)update(L, R, k, rson);
up(i);
}
int query(int l, int r, int i) {
if (l == r)return l;
int ans = -, mid = l + r >> ;
down(i);
if (Max[i << ] == c)ans = query(lson);
else if (Max[i << | ] == c)ans = query(rson);
return ans;
}
int a[maxn];
int main() {
while (scanf("%d%d%d", &n, &c, &k) != EOF) {
for (int i = ; i <= c; i++)
cnt[i].clear(), cnt[i].push_back(), num[i] = ;
for (int i = ; i <= n; i++) {
scanf("%d", &a[i]);
cnt[a[i]].push_back(i);
}
build(, n, );
for (int i = ; i <= c; i++) {
cnt[i].push_back(n + );
update(cnt[i][] + , cnt[i][] - , , , n, );
}
int ans = ;
for (int i = ; i <= n; i++) {
update(cnt[a[i]][num[a[i]]] + , cnt[a[i]][num[a[i]] + ] - , -, , n, );
if (num[a[i]] >= k)
update(, cnt[a[i]][num[a[i]] - k + ], -, , n, );
num[a[i]]++;
update(cnt[a[i]][num[a[i]]] + , cnt[a[i]][num[a[i]] + ] - , , , n, );
if (num[a[i]] >= k)
update(, cnt[a[i]][num[a[i]] - k + ], , , n, );
int q = query(, n, );
if (q != -)
ans = max(ans, i - q + );
}
printf("%d\n", ans);
}
}

[2019杭电多校第二场][hdu6602]Longest Subarray(线段树)的更多相关文章

  1. 2019杭电多校第二场hdu6602 Longest Subarray(线段树)

    Longest Subarray 题目传送门 解题思路 本题求一个最大的子区间,满足区间内的数字要么出现次数大于等于k次,要么没出现过.给定区间内的数字范围是1~c. 如果r为右边界,对于一种数字x, ...

  2. 2019杭电多校第二场hdu6601 Keen On Everything But Triangle

    Keen On Everything But Triangle 题目传送门 解题思路 利用主席树求区间第k小,先求区间内最大的值,再求第二大,第三大--直到找到连续的三个数可以构成一个三角形.因为对于 ...

  3. [2019杭电多校第二场][hdu6601]Keen On Everything But Triangle

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6601 题意是说用给定区间内的数字组成周长最大的三角形. 大致做法就是求区间第1大,第2大和第3大然后判 ...

  4. [2019杭电多校第二场][hdu6599]I Love Palindrome String(回文自动机&&hash)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6599 题目大意为求字符串S有多少个子串S[l,r]满足回文串的定义,并且S[l,(l+r)/2]也满足 ...

  5. [2019杭电多校第二场][hdu6598]Harmonious Army(最小割)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6598 题意是说一个军队有n人,你可以给他们每个人安排战士或者法师的职业,有m对人有组合技,组合技的信息 ...

  6. 2019牛客多校第二场E MAZE(线段树 + 矩阵)题解

    题意: n * m的矩阵,为0表示可以走,1不可以走.规定每走一步只能向下.向左.向右走.现给定两种操作: 一.1 x y表示翻转坐标(x,y)的0.1. 二.2 x y表示从(1,x)走到(n,y) ...

  7. 2018 Multi-University Training Contest 2 杭电多校第二场

    开始逐渐习惯被多校虐orz  菜是原罪 1004  Game    (hdoj 6312) 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6312 虽然披着 ...

  8. 2019年杭电多校第二场 1012题Longest Subarray(HDU6602+线段树)

    题目链接 传送门 题意 要你找一个最长的区间使得区间内每一个数出现次数都大于等于\(K\). 思路 我们通过固定右端点考虑每个左端点的情况. 首先对于每个位置,我们用线段树来维护它作为\(C\)种元素 ...

  9. 2019年杭电多校第二场 1008题Harmonious Army(HDU6598+最小割+建图)

    题目链接 传送门 题意 有\(n\)个士兵,要你给他们分配职业.有\(m\)对关系,对于某一对关系\(u,v\),如果同为勇士则总能力增加\(a\),同法师则增加\(c\),一个勇士一个法师增加\(\ ...

随机推荐

  1. Java课后作业04

    一.古罗马皇帝凯撒在打仗时曾经加密军事情报: 1.设计思想: 加密原理是abc等全部后移3位xyz分别等于abc,根据ascii码表的转化,将其利用charat()取单个字符进行转化,再利用Strin ...

  2. 【微信小程序】使用vscode编写微信小程序项目

    1. 在微信开发者工具(以下简称:开发者)中新建一个模板微信小程序 2. 在开发者中将模拟器分隔开 3. 设置在保存时编译 4. 在vscode中打开项目目录 5. 下载代码提示插件 这样就可以在vs ...

  3. LTM_本地流量管理(二)

    会话保持 首先要熟悉两个概念:连接connect和会话session 连接:在四层负载均衡中,连接是最小元素. l  源端口:客户端随机产生的端口. l  源地址:发起请求的源IP地址. l  目的端 ...

  4. C#与.NET Framework c#编程语言,和java是一样的。(c#,java) -->javaweb,asp.net

  5. 判断Java对象存活的算法、垃圾回收算法

    判断Java对象存活的算法 一.引用计数算法 给对象添加一个引用计数器,每当一个地方引用它的时候就将计数器加1,当引用失效的时候就将计数器减1,任何时刻计数器为0的对象都不可再被使用.这种算法虽然简单 ...

  6. CF643E Bear and Destroying Subtrees

    题解 我们可以先写出\(dp\)式来. 设\(dp[u][i]\)表示以\(u\)为根的子树深度不超过\(i-1\)的概率 \(dp[u][i]=\prod (dp[v][i-1]+1)*\frac{ ...

  7. Matlab 中 函数circshift()的用法

    a = [ ; ; ]; b = [- - -; - - -;- - -]; c = [ ; ; ]; Hist(:,:,) = a; Hist(:,:,) = b; Hist(:,:,) = c; ...

  8. 高通Android camera运行流程【转】

    本文转载自:http://blog.csdn.net/unicornkylin/article/details/13293295 1.总体架构 Android Camera 框架从整体上看是一个 cl ...

  9. Linux下查看分区内目录及文件占用空间容量

    转载linux下使用 du查看某个文件或目录占用磁盘空间的大小   du -ah --max-depth=1     这个是我想要的结果  a显示目录占用的磁盘空间大小,还要显示其下目录和文件占用磁盘 ...

  10. day03-Python基础

    1:函数 定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 减少重复代码 使程序变的可扩展 使程序变得易维护 函数定义: def sayh ...