题意:

1e5的数组,c(1e5)种数字求最长的子串,使得其中每个出现的数字出现的次数为0次或者大于k次

思路:

枚举右端点i,维护当前右端点时,每个左端点的可行元素数量,当且仅当可行元素为c时更新答案

每次用最左边的可行的左端点与当前右端点更新答案

对于每个元素,如果它从i往左第1次出现的元素为pos1,第k次出现的为pos2

那么该元素的可行区域为[1,pos2]与[pos1+1,i]

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map> #define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1 using namespace std; typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL; const db eps = 1e-;
const int mod = 1e9+;
const int maxn = 2e5+;
const int maxm = 4e6+;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0); int n,c,k;
int a[maxn];
vector<int>v[maxn];
int mx[maxn<<];
int addv[maxn<<];
void build(int l, int r, int root){
int mid = (l+r)>>;
if(l==r){mx[root]=c;return;}
build(lson);
build(rson);
mx[root]=max(mx[lc],mx[rc]);
addv[root]=;
return;
}
void pushdown(int l, int r, int root){
if(addv[root]){
addv[lc]+=addv[root];
addv[rc]+=addv[root];
mx[lc]+=addv[root];
mx[rc]+=addv[root];
addv[root]=;
}
return;
}
void update(int x, int y, int val, int l, int r, int root){
int mid = (l+r)>>;
if(x<=l&&r<=y){
addv[root]+=val;
mx[root]+=val;
return;
}
pushdown(l,r,root);
if(x<=mid)update(x,y,val,lson);
if(y>mid)update(x,y,val,rson);
mx[root]=max(mx[rc],mx[lc]);
return;
}
int ask(int l, int r, int root){
int mid = (l+r)>>;
if(l==r){
if(mx[root]==c)return l;
else return inf;
}
pushdown(l,r,root);
if(mx[lc]==c)return ask(lson);
else if(mx[rc]==c)return ask(rson);
return inf;
} int main(){
while(~scanf("%d %d %d", &n, &c, &k)){
for(int i = ; i <= n; i++){v[i].clear();v[i].pb();}
for(int i = ; i <= n; i++){
scanf("%d", &a[i]);
}
build(,n,);
int ans = ;
for(int i = ; i <= n; i++){
if((int)v[a[i]].size()>k){
int l = v[a[i]][v[a[i]].size()-k];
int r = v[a[i]].back();
update(l+,r,,,n,);
v[a[i]].pb(i);
l=v[a[i]][v[a[i]].size()-k];
r=v[a[i]].back();
update(l+,r,-,,n,);
}
else{
update(v[a[i]].back()+,i,-,,n,);
v[a[i]].pb(i);
if((int)v[a[i]].size()>k){
int l = v[a[i]][v[a[i]].size()-k];
update(,l,,,n,);
}
}
int L = ask(,n,);
ans=max(ans,max(,i-L+));
}
printf("%d\n",ans);
}
return ;
}
/*
7 5 2
3 1 5 2 5 2 3 */

HDU 6602 Longest Subarray (线段树)的更多相关文章

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

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

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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6602 题目大意为求最长的区间,满足C种数字在区间内要么不出现,要么出现的次数都不小于K. 大致的分析一 ...

  3. 2019杭电多校二 L. Longest Subarray (线段树)

    大意: 给定序列$a$, 元素范围$[1,C]$, 求一个最长子序列, 满足每个元素要么不出现, 要么出现次数$\le K$. 枚举右端点, 考虑左端点合法的位置. 显然一定是$C$种颜色合法位置的交 ...

  4. hdu 5700区间交(线段树)

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  5. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

  6. Hdu 3564 Another LIS 线段树+LIS

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...

  7. HDU 5091---Beam Cannon(线段树+扫描线)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5091 Problem Description Recently, the γ galaxies bro ...

  8. HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  9. HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Sub ...

随机推荐

  1. WPF 给Button按钮加小图标图片Image

    前言:当WPF项目后台完成到一定程度的时候,就可以对XAML前端进行美化啦,个人认为XAML前端还是挺有意思的. 下面举一个Button加过小图标后的例子: 是不是比生硬的文字看来更人性化了呢? 不多 ...

  2. spring get方法 中文(UTF-8)乱码

    问题: 前端用Get方法进行如下请求: 在浏览器中输入:http://localhost:8080/dmaList/ExportBySQL?sql=&names=分区级别&size=1 ...

  3. 探究公钥、私钥、对称加密、非对称加密、hash加密、数字签名、数字证书、CA认证、https它们究竟是什么,它们分别解决了通信过程的哪些问题。

    一.准备 1. 角色:小白.美美.小黑. 2. 剧情:小白和美美在谈恋爱:小黑对美美求而不得.心生怨念,所以从中作梗. 3. 需求:小白要与美美需通过网络进行通信,联络感情,所以必须保证通信的安全性. ...

  4. 2次方的期望dp

    某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:(    我们来简化一下这个游戏的规则    有n次点击要做,成功了就是o,失败了就是x,分数是按comb计算的,连续a个com ...

  5. KVM虚拟化基础

    关于虚拟化 什么是虚拟化 在计算机技术中,虚拟化(技术)或虚拟技术(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源(CPU.内存.磁盘空间.网络适配器等),予以抽象. ...

  6. Nginx模块讲解

    Nginx模块分为:nginx官方模块.第三方模块 通过nginx -V查看编译参数,可以看到官方编译的模块 --with-compat --with-file-aio --with-threads ...

  7. MySQL多表联查以及以及架构

    多表之间关联查询:      据库操作中,多表联合查询是后台开发者常用到的查询语句. JOIN SQL JOIN 子句用于把来自两个或多个表的行结合起来,最常见的 JOIN 类型:SQL INNER ...

  8. KMP——强大的next数组

    \(KMP\) 的原理不在这里仔细讲了,主要说说最近刷题总结出的 \(next\) 数组的强大功能. 部分例题来自<信息学奥赛一本通>的配套练习. 基于定义--字符串相同前后缀 " ...

  9. linux 为动态分配的Virtualbox虚拟硬盘扩容

    如何为动态分配的Virtualbox虚拟硬盘扩容 查看虚拟硬盘是否是动态分配大小 打开虚拟机的设置界面,在左侧栏点击存储.在存储树下面选择你的虚拟硬盘.在右边可以看见虚拟硬盘的信息.在下面可以看见,我 ...

  10. selenium2-Python环境搭建

    一.什么是selenium? selenium主要用于web应用的自动化测试,但并不局限于此,它还支持基于所有web的管理任务自动化,且开源免费,多浏览器支持(IE,Mozilla Firefox,S ...