题目链接:点击查看

题目大意:给出一个长度为 n 的序列,每个数字的范围是 [ 1 , C ] ,现在需要求一个子串,使得字串中的字母,要么出现 0 次,要么出现至少 K 次,问这个子串的最大长度是多少

题目分析:第一反应是二分+尺取,但感觉会超时,正解是线段树,枚举 1 ~ n 作为子串的右端点,然后贪心找符合条件的左端点

对于任意一个位置 i ,再对于任意一个数字 b 来说,设 pos1 是数字 b 从位置 i 向左开始第一次出现的位置,pos2 是第 k 次出现的位置,pos3 是第 k - 1 次出现的位置(下面会用到),则对于数字 b 来说,可以选择的左端点的区间范围是 [ 1 , pos2 ] 和 [ pos1 + 1 , i ]

这样当我们枚举位置 i 时,假设位置 i 的数字为 num ,其前一次出现的位置为 pre,则因为第 i 个位置是 num,所以区间 [ pre + 1 , i ] 这段区间对左端点的贡献集体减一,因为如果还没有第 i 个数字出现的话,那么对于数字 num 来说,区间 [ pre + 1 , i - 1 ] 这段区间对左端点的贡献都为 1 ,所以当加入第 i 个位置的 num 后,需要群体减一

同时,因为新加入了一个 num 的位置,所以原先 [ 1 , pos2 ] 的这段区间扩大到了 [ 1 , pos3 ] 这么大,相当于 [ pos2 + 1 , pos3 ] 这段区间对左端点的贡献集体加一了

因为对于贡献来说,既有群体加一,又有群体减一,所以当一个节点的相对贡献大于等于 0 时,说明当前节点可以选做为左端点,每次处理完后,贪心去寻找相对贡献大于等于 0 的最左端的位置,然后更新答案即可

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;vector<int>pos[N];struct Node
{int l,r,mmax,lazy;
}tree[N<<2];void pushup(int k)
{tree[k].mmax=max(tree[k<<1].mmax,tree[k<<1|1].mmax);
}void pushdown(int k)
{if(tree[k].lazy){int lz=tree[k].lazy;tree[k].lazy=0;tree[k<<1].lazy+=lz;tree[k<<1].mmax+=lz;tree[k<<1|1].lazy+=lz;tree[k<<1|1].mmax+=lz;}
}void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;tree[k].mmax=tree[k].lazy=0;if(l==r)return;int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}void update(int k,int l,int r,int val)
{if(tree[k].r<l||tree[k].l>r)return;if(tree[k].l>=l&&tree[k].r<=r){tree[k].lazy+=val;tree[k].mmax+=val;return;}pushdown(k);update(k<<1,l,r,val);update(k<<1|1,l,r,val);pushup(k);
}int query(int k)
{if(tree[k].mmax<0)return inf;if(tree[k].l==tree[k].r)return tree[k].l;pushdown(k);if(tree[k<<1].mmax>=0)return query(k<<1);elsereturn query(k<<1|1);
}void init(int c)
{for(int i=1;i<=c;i++){pos[i].clear();pos[i].push_back(0);}
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n,c,k;while(scanf("%d%d%d",&n,&c,&k)!=EOF){init(c);build(1,1,n);int ans=0;for(int i=1;i<=n;i++){int num;scanf("%d",&num);update(1,pos[num].back()+1,i,-1);if(pos[num].size()>k)update(1,1,pos[num][pos[num].size()-k],-1);pos[num].push_back(i);if(pos[num].size()>k)update(1,1,pos[num][pos[num].size()-k],1);ans=max(ans,i-query(1)+1);}printf("%d\n",ans);}return 0;
}

HDU - 6602 Longest Subarray(线段树+思维)相关推荐

  1. HDU6599多校第二场 Longest Subarray -- 线段树

    http://acm.hdu.edu.cn/showproblem.php?pid=6602 题意:给出一个长度的为n的数字,其中数字都是1-C,即只有C种数,要求选出一个长度最大的区间,使得其中C个 ...

  2. HDU - 6315 Naive Operations(线段树+思维)

    题目链接:点击查看 题目大意:给出一个数列 a 和一个数列 b ,其中数列 a 初始时全部为 0 ,数列 b 初始时是一个 1 ~ n 的排列,接下来共有 m 次操作,每次操作分为两种: add l ...

  3. hdu 3397 Sequence operation(线段树,lazy,区间合并)

    hdu 3397 Sequence operation 线段树lazy和区间合并结合的一个题,相当于几个题集中到一起嘛,分开想就好了 0,1,2操作都要lazy,2的异或操作找到每一只含1或只含0的区 ...

  4. 线段树——思维(Codeforces 339D Xenia and Bit Operations/Billboard HDU - 2795)

    Codeforces 339D Xenia and Bit Operations vj地址 题意:给出2的n次方个数,每次将现在这个序列中相邻的两个数运算后合并为一个数,得到一个新的序列,这个新序列的 ...

  5. hdu 4747 mex 线段树+思维

    http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意: 我们定义mex(l,r)表示一个序列a[l]....a[r]中没有出现过得最小的非负整数, 然后我 ...

  6. HDU - 6992 Lawn of the Dead 线段树 + 思维

    传送门 文章目录 题意: 思路: 题意: 给你一张n∗mn*mn∗m的图,其中有kkk个点不能走,你只能向下和向右走,问你能到达多少点. n,m,k≤1e5n,m,k\le1e5n,m,k≤1e5 思 ...

  7. 2016 Multi-University Training Contest 10 [HDU 5861] Road (线段树:区间覆盖+单点最大小)...

    HDU 5861 题意 在n个村庄之间存在n-1段路,令某段路开放一天需要交纳wi的费用,但是每段路只能开放一次,一旦关闭将不再开放.现在给你接下来m天内的计划,在第i天,需要对村庄ai到村庄bi的道 ...

  8. hdu 2871 Memory Control(线段树)

    题目链接:hdu 2871 Memory Control 题目大意:模拟一个内存分配机制. Reset:重置,释放全部空间 New x:申请内存为x的空间,输出左地址 Free x:释放地址x所在的内 ...

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

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

最新文章

  1. 200万年薪,招不到清华姚班毕业生,能上姚班的都是什么人?
  2. Hyper-V 网卡 load failed
  3. 用神经网络计算甲醛CH2O和亚硝酸HNO2的化学键的键能
  4. C++中public、protected及private用法
  5. 7. webpack 初步熟悉使用
  6. [Leetcode]@python 68. Text Justification
  7. sanic官方文档解析之下载和Configuration
  8. authentication java_HTTP基本认证(Basic Authentication)的JAVA实例代码
  9. 将excel里面的数据直接生成sql语句
  10. Delphi XE2有什么新功能
  11. MindManager中读图工具的使用
  12. mtkwin10驱动_【MTK通用USB刷机驱动下载】MTK通用USB刷机驱动 Win7/Win10 自动安装版-开心电玩...
  13. 在中国知网下载 PDF 格式的学位论文
  14. 蓝屏(BSOD)转储设置,看本文就够了!
  15. 天池大数据竞赛——UI特征统计
  16. webpack中loader和plugin的区别
  17. 王之泰201771010131《面向对象程序设计(java)》第八周学习总结
  18. php 问号乱码,如何解决php问号乱码的问题
  19. 根据出生年月日计算出生了多少年,多少月,多少天
  20. 桌面终端运维常见问题

热门文章

  1. dr.com linux源码安装,Linux在不采用坑爹的Dr.com客户端下的连网方式(亲测可行 ,简单易行)...
  2. xyz后缀的网站_.XYZ五岁了
  3. layui导入模板数据_layui表格-template模板的三种用法
  4. Nginx的rewrite之rewrite指令
  5. Nginx系统环境准备
  6. 为什么需要实现幂等性?
  7. ArrayBlockingQueue原理分析-take方法
  8. Spring 中的编程思想总结
  9. aop简介-基于jdk的动态代理
  10. Spring编程模型:Spring实现了哪些编程模型?