链接:https://www.nowcoder.net/acm/contest/58/E

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给你一个长为n的序列a,m次查询区间[l,r]内出现次数第k1小的数中值第k2小的数是多少?
保证输入合法

输入描述:

第一行一个数n
第二行n个数表示序列a
第三行一个数m
之后m行每行四个数表示l r k1 k2

输出描述:

对于每次询问输出一行一个数表示答案

输入例子:
10
3 6 6 8 3 10 1 6 5 6
10
4 7 1 2
5 7 1 1
5 6 1 2
2 6 2 1
8 9 1 1
6 9 1 2
1 2 1 1
1 4 2 1
5 7 1 3
2 6 1 3
输出例子:
3
1
10
6
5
5
3
6
10
10

-->

示例1

输入

10
3 6 6 8 3 10 1 6 5 6
10
4 7 1 2
5 7 1 1
5 6 1 2
2 6 2 1
8 9 1 1
6 9 1 2
1 2 1 1
1 4 2 1
5 7 1 3
2 6 1 3

输出

3
1
10
6
5
5
3
6
10
10

说明

3 6 6 8 3 10 1 6 5 6
[4,7]中出现1次的有1,3,8,10,第2小的是3
[5,7]中出现1次的有1,3,10,第1小的是1
[5,6]中出现1次的有3,10,第2小的是10
[2,6]中出现2次的有6,第1小的是6
[8,9]中出现1次的有5,6,第1小的是5
[6,9]中出现1次的有1,5,6,10,第2小的是5
[1,2]中出现1次的有3,6,第1小的是3
[1,4]中出现2次的有6,第1小的是6
[5,7]中出现1次的有1,3,10,第3小的是10
[2,6]中出现1次的有3,8,10,第3小的是10

备注:

对于100%的数据,
有1<=n,a[i],m<=40000
数据保证一定能找到那个数

这一题没有码出来,去看了一下别人提交的代码看懂就没自己写了

/////////////////////////////////////////////////

可以考虑进行高维离散化

比如说,对于一个数x,其在序列中出现了y次

开个vector < int > v[ MAXN ]

在v[1] , v[2] ... v[y]中都push_back( x )

然后对于每个vector,分别进行离散化

这样就保证了空间线性

在高维离散化的基础上进行值域分块,然后跑莫队即可

O( nsqrtm + msqrtn ) = O( msqrtn )

/////////////////////////////////////////////////

题解里是高维离散化,但是我看到的代码我感觉那位大佬写的好像更好一点,

他是用了两次分块,次数分块和值分块

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int read(){
int x=,f=;char ch=getchar();
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
return x*f;
}
const int N=; int n,m,have[N],a[N],ap[N],cnt[N][],cntk[],ans[N],pos,bb,blo,L,R;
//have[i]表示是否有次数为i的值出现
//ap[i]表示值为i的数字出现了几次
//cntk[i]表示有多少个不同数值出现了k次,k处在i块里
//cnt[i][j]表示出现了i次的值里,值处在j块有多少
struct node{
int l,r,blo,id,k1,k2;
}q[N]; bool operator < (const node &A,const node &B){
return A.blo<B.blo||A.blo==B.blo&&A.r<B.r;
} void work(int x,int w){
int val=a[x],cc=ap[val];
if (!--have[cc]) cntk[(cc-)/bb+]--;
cnt[cc][(val-)/bb+]--;
ap[val]+=w;cc=ap[val];
if (++have[cc]==) cntk[(cc-)/bb+]++;
cnt[cc][(val-)/bb+]++; //[次数][值所属的块]
} int qry(int k1,int k2){
int i=,j;
while (k1>cntk[i]) k1-=cntk[i],i++;//sqrt(n),次数所属的块,每个块有多少个出现了
for (j=(i-)*bb+;j<=i*bb;j++)//sqrt(n)
if (have[j])
if (!--k1) break;
pos=j;i=;//k1小的是j次/pos次
while (k2>cnt[pos][i]) k2-=cnt[pos][i],i++;//sqrt(n)
for (j=(i-)*bb+;j<=i*bb;j++)//sqrt(n)
if (ap[j]==pos)
if (!--k2) break;
return j;
}
int main(){ n=read();bb=(int)sqrt(n);
for (int i=;i<=n;i++) a[i]=read();
m=read();blo=(int)sqrt(m);
for (int i=;i<=m;i++)
q[i].l=read(),q[i].r=read(),q[i].k1=read(),
q[i].k2=read(),q[i].id=i,q[i].blo=(q[i].l-)/blo+;
sort(q+,q+m+);
L=;R=;
for (int i=;i<=m;i++)
{
while (L>q[i].l) work(--L,);
while (R<q[i].r) work(++R,);
while (L<q[i].l) work(L++,-);
while (R>q[i].r) work(R--,-);
ans[q[i].id]=qry(q[i].k1,q[i].k2);
}
for (int i=;i<=m;i++) printf("%d\n",ans[i]);
return ;
}

引用了别的大佬的代码,加了一点注释

分块自己用的还是很生涩,惨

假如是高维离散化的话,应该得跟f题一样用链表存一下出现的次数,然后每个次数里面的值再分块查询,emm就这样

wannafly 练习赛10 E 数列查找(莫队+分块分块分块......)的更多相关文章

  1. wannafly 练习赛10 f 序列查询(莫队,分块预处理,链表存已有次数)

    链接:https://www.nowcoder.net/acm/contest/58/F 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C++ 262144K,其他语言524288K 64 ...

  2. (原创)BZOJ 2038 小Z的袜子(hose) 莫队入门题+分块

    I - 小Z的袜子(hose) 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z ...

  3. POJ 2104 - 主席树 / 询问莫队+权值分块

    传送门 题目大意应该都清楚. 今天看到一篇博客用分块+莫对做了这道题,直接惊呆了. 首先常规地离散化后将询问分块,对于某一询问,将莫队指针移动到指定区间,移动的同时处理权值分块的数字出现次数(单独.整 ...

  4. 2019.01.08 bzoj3809: Gty的二逼妹子序列(莫队+权值分块)

    传送门 题意:多组询问,问区间[l,r]中权值在[a,b]间的数的种类数. 看了一眼大家应该都知道要莫队了吧. 然后很容易想到用树状数组优化修改和查询做到O(mnlogamax)O(m\sqrt nl ...

  5. BZOJ 3339 && BZOJ 3585 莫队+权值分块

    显然若一个数大于n就不可能是答案. #include <iostream> #include <cstring> #include <cstdio> #includ ...

  6. 莫队+分块 BZOJ 3809

    3809: Gty的二逼妹子序列 Time Limit: 80 Sec  Memory Limit: 28 MBSubmit: 1634  Solved: 482[Submit][Status][Di ...

  7. 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)

    2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...

  8. 【BZOJ】2038: [2009国家集训队]小Z的袜子(hose)(组合计数+概率+莫队算法+分块)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2038 学了下莫队,挺神的orzzzz 首先推公式的话很简单吧... 看的题解是从http://for ...

  9. 【BZOJ4129】Haruna’s Breakfast(树上莫队)

    [BZOJ4129]Haruna's Breakfast(树上莫队) 题面 BZOJ Description Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了 ...

随机推荐

  1. BATJ的常见java面试题

    JAVA基础 JAVA中的几种基本数据类型是什么,各自占用多少字节. String类能被继承吗,为什么. 不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允 ...

  2. CF 1141C Polycarp Restores Permutation

    Description An array of integers p1,p2,…,pnp1,p2,…,pn is called a permutation if it contains each nu ...

  3. 设备程序远程升级采用两种方式(优先采用IP方式)

    设备程序远程升级采用两种方式(优先采用IP方式): 采用应急广播TS流传输技术规范的消息内容表携带升级包数据.当辅助数据类型值为44时,消息内容表传输的数据为程序升级包. 采用IP方式传输升级包数据. ...

  4. 微信内置浏览器不支持 onclick 如何解决?(原因是因为内面中的内容或者标签大部分是动态生成的)

    使用了很多onclick事件,但是在Android的微信内置浏览器中,onclick是不能被执行的. 开始的写法是: // $(".contentPic").click(funct ...

  5. Java Script 基本知识点

                          JavaScript是一种基于对象和事件驱动的脚本语言,它提供了一些专有的类.对象及函数 1.基本数据类型 JavaScript提供了4种基本的数据类型用来 ...

  6. src和href都是链接有啥不一样

    前言 src和href都是用于外部资源的引入,像图片.CSS文件.HTML文件.js文件或其他web页面等.那么在SRC和HREF之间是否有一个明确的区别呢?在哪些地方或者什么时候应该用SRC还是HR ...

  7. postgresql 相关操作

    1.root 用户,执行 service postgresql restart service postgresql start  --启动 2.查看数据库状态 /etc/init.d/postgre ...

  8. 关于python3.4版本中的zip函数

    特别注意: 在window,显示变量 print(x);而在linux中 print x 例如,有两个列表: >>>a = [1,2,3] >>>b = [4,5, ...

  9. Android 一共有多少种动画?准确告诉你!

    Android 动画 Android 动画在开发中是不可或缺的功能,或者说是界面灵动的添加剂.那你是否总结过 Android 中总共为开发者提供了多少种方式的动画呢?今天就为大家总结归纳一下.   报 ...

  10. Redis启动方式

    一.前端启动 直接运行bin/redis-server将以前端模式启动.[bin目录是在/usr/local/redis/bin] # ./redis-server 启动缺点: ssh命令窗口关闭则r ...