51nod 1686 第K大区间 二分瞎搞
题目:
定义一个区间的值为其众数出现的次数。
现给出n个数,求将所有区间的值排序后,第K大的值为多少。
题解:
答案明显单调,我们考虑二分答案.
转化为判定问题后我们需要观察到一个性质:
如果一个区间的价值已经 >= mid了,那么这个无论左右端点向外延伸多少,区间价值一定仍然 >= mid
所以我们可以考虑找出所有的最小满足限制的区间,然后计算出可延伸区间。
所以我们枚举右端点,根据右端点找出对应的左端点,然后统计答案.
我们发现:根据右端点向右移动,左端点一定也向右移动。
所以我们使用双指针法,每一次计算出右端点所代表的值的上mid-1次出现的位置
用这个位置和左端点指针取max,每一次让ans += 所有<=下标左端点的点的个数.
单次判定\(O(n)\),总体\(O(nlogn)\)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline void read(ll &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 120000;
int last[maxn],nxt[maxn];
int b[maxn],n,a[maxn],c[maxn],pos[maxn];
inline void init(){
memset(last,0,sizeof last);
memset(nxt,0,sizeof nxt);
memset(b,0,sizeof b);
}
inline ll check(int val){
ll ret = 0;
init();memset(c,0,sizeof c);
for(int i=1;i<=n;++i){
last[i] = c[a[i]];
c[a[i]] = i;
}memset(c,0,sizeof c);
for(int i=n;i>=1;--i){
nxt[i] = c[a[i]];
c[a[i]] = i;
}
memset(c,0,sizeof c);
memset(pos,0,sizeof pos);
for(int i=1;i<=n;++i){
if(++c[a[i]] == 1) pos[a[i]] = i;
if(c[a[i]] == val) b[i] = pos[a[i]];
else if(c[a[i]] > val){
b[i] = nxt[b[last[i]]];
}
}
if(val == 1) for(int i=1;i<=n;++i) b[i] = i;
for(int L=0,R=1;R <= n;++R){
L = max(L,b[R]);
ret += L;
}
return ret;
}
int main(){
read(n);ll k;read(k);
for(int i=1;i<=n;++i){
read(a[i]);b[i] = a[i];
}
sort(b+1,b+n+1);
for(int i=1;i<=n;++i){
a[i] = lower_bound(b+1,b+n+1,a[i]) - b;
}
int l = 1,r = n,ans = 0;
while(l <= r){
int mid = (l+r) >> 1;
if(check(mid) >= k) ans = mid,l = mid+1;
else r = mid-1;
}
printf("%d\n",ans);
return 0;
}
51nod 1686 第K大区间 二分瞎搞的更多相关文章
- 51NOD 1686 第K大区间 二分
第k大区间 定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. Input 第一行两个数n和k(1<=n<=100000,k<=n* ...
- 51nod 1686 第k大区间
1686 第K大区间 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. ...
- 51nod 1686 第K大区间2
1685 第K大区间2 定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. 众数(统计学/数学名词)_百度百科 Input 第一行两个数n和k(1<=n ...
- 51nod 1686 第K大区间【离散化+二分】
题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1686 题意: 定义一个区间的值为其众数出现的次数. 现给出n ...
- 51Nod 1686 第K大区间(离散化+尺取法)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1686 题意: 思路: 第K大值,所以可以考虑二分法,然后用尺取法去扫描, ...
- 【题解】51nod 1686第K大区间
成功的秘诀,在于克服自己看题解的冲动……[笑哭].自己A掉这题还是灰常开心的~ 以及爱死 two - pointer ! two - pointer 大法是真的好哇……这个题目有上一题的经验:求第\( ...
- 1686 第K大区间(尺取+二分)
1686 第K大区间 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. ...
- 1686 第K大区间
1686 第K大区间 时间限制:1 秒 空间限制:131072 KB 定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. 众数(统计学/数学名词)_百度百 ...
- 51nod-1686 第K大区间(二分+尺取法)
题目链接: 第K大区间 基准时间限制:1 秒 空间限制:131072 KB 定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. Input 第一行两个数 ...
随机推荐
- 关于function的一种常用用法
关于function的一种常用用法 void Share::InitAcrossManager() { GsMgrEvent gsMgrEvents;//保存function的结构体 gsMgrEve ...
- Java Enum 比较用 == 还是 eques
我是把枚举当作常量来使用的,枚举中还有两个自己的属性,关注到这个地方的朋友对枚举已经有了认识,这里就不再编写枚举的demo了,这里我直接说结果吧,在枚举中使用==和equals比较效果是一样的,查看源 ...
- 【BZOJ4028】[HEOI2015]公约数数列 分块
[BZOJ4028][HEOI2015]公约数数列 Description 设计一个数据结构. 给定一个正整数数列 a_0, a_1, ..., a_{n - 1},你需要支持以下两种操作: 1. M ...
- debian安装oracle jdk
1 去官网下载linux jdk https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.htm ...
- 【译】Java语言速览:StackOverflow
Java (请不要与 JavaScript 搞混) 是一种设计为与 Java 虚拟机 (JVM) 一起使用的多用途编程语言.一般称呼安装了相关工具使其可以开发并运行 Java 程序的电脑系统为 &qu ...
- 几则js表达式
过滤大段文本里的标签.标签格式 <...>,如下匹配标签然后替换成空 校验邮箱是否符合: 去掉行首行尾空格: 检测字符串是否包含中文:(utf8编码)
- linux c编程:进程控制(四)进程调度
当系统中有多个进程到时候,哪个进程先执行,哪个进程后执行是由进程的优先级决定的.进程的优先级是由nice值决定的.nice值越小,优先级越高.可以看做越友好那么调度优先级越低.进程可以通过nice函数 ...
- CentOS7.x 报错 There are no enabled repos.
地址 :http://mirrors.163.com/centos/7/os/x86_64/Packages/ wget http://mirrors.163.com/centos/7/os/x8 ...
- centos 安装 jdk PostgreSQL
1.下载: anzhuang jDK http://blog.csdn.net/youzhouliu/article/details/51183115 ----------------------- ...
- C#聚合运算方法
Aggregate 对集合值执行自定义聚合运算 Average 计算集合平均值 Count 对集合的元素惊醒计数,还可以仅对满足某一谓词函数的元素进行计数 LongCount 对大型集合中的元素进行计 ...