wannafly 练习赛10 E 数列查找(莫队+分块分块分块......)
链接:https://www.nowcoder.net/acm/contest/58/E
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
保证输入合法
输入描述:
- 第一行一个数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
-->
输入
- 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 数列查找(莫队+分块分块分块......)的更多相关文章
- wannafly 练习赛10 f 序列查询(莫队,分块预处理,链表存已有次数)
链接:https://www.nowcoder.net/acm/contest/58/F 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C++ 262144K,其他语言524288K 64 ...
- (原创)BZOJ 2038 小Z的袜子(hose) 莫队入门题+分块
I - 小Z的袜子(hose) 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z ...
- POJ 2104 - 主席树 / 询问莫队+权值分块
传送门 题目大意应该都清楚. 今天看到一篇博客用分块+莫对做了这道题,直接惊呆了. 首先常规地离散化后将询问分块,对于某一询问,将莫队指针移动到指定区间,移动的同时处理权值分块的数字出现次数(单独.整 ...
- 2019.01.08 bzoj3809: Gty的二逼妹子序列(莫队+权值分块)
传送门 题意:多组询问,问区间[l,r]中权值在[a,b]间的数的种类数. 看了一眼大家应该都知道要莫队了吧. 然后很容易想到用树状数组优化修改和查询做到O(mnlogamax)O(m\sqrt nl ...
- BZOJ 3339 && BZOJ 3585 莫队+权值分块
显然若一个数大于n就不可能是答案. #include <iostream> #include <cstring> #include <cstdio> #includ ...
- 莫队+分块 BZOJ 3809
3809: Gty的二逼妹子序列 Time Limit: 80 Sec Memory Limit: 28 MBSubmit: 1634 Solved: 482[Submit][Status][Di ...
- 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)
2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...
- 【BZOJ】2038: [2009国家集训队]小Z的袜子(hose)(组合计数+概率+莫队算法+分块)
http://www.lydsy.com/JudgeOnline/problem.php?id=2038 学了下莫队,挺神的orzzzz 首先推公式的话很简单吧... 看的题解是从http://for ...
- 【BZOJ4129】Haruna’s Breakfast(树上莫队)
[BZOJ4129]Haruna's Breakfast(树上莫队) 题面 BZOJ Description Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了 ...
随机推荐
- __strong修饰符
本文用来观察,对于__strong修饰符,编译器为我们自动添加了什么代码,这些代码对于引用计数有什么影响. 例子一 X __strong *x1 = [[X alloc] init]; 使用控制台打印 ...
- 使用批处理选择运行控制台程序(简易cui)
批处理可以用于启动一些控制台程序.昨天在github上找到一个有意思的项目OpenRA : 一个开源的红警游戏. 发现该游戏的启动程序(launch-game)是用批处理写的 就学习了下 *没有玩过批 ...
- Head First PHP&MySQl第二章代码
PHP: <html> <head> <title>外星人绑架了我--报道一起绑架</title> </head> <body> ...
- [Vue] vue的一些面试题
1.v-model 的原理 v-model 是一个语法糖,它即可以支持原生表单元素,也可以支持自定义组件.v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件. text 和 text ...
- ivew组件上传图片文件的功能:
解决的问题: 1.使用view的<Upload>组件实现图片文件的上传. 2.<Upload>组件action请求地址无法到自己写的后台. 3.前台base64的图片展示. 4 ...
- icmp, IPPROTO_ICMP - Linux IPv4 ICMP 核心模块.
DESCRIPTION 描述 本网络核心协议模块实现了基于 RFC792 协议中定义的<互联网控制报文协议>.它针对网络主机间通讯出错的情况作出回应并给出诊断信息.用户不能直接使用本模块. ...
- laravel5.8 Auth::guide
// 使用下面这个命令Laravel会自动为我们生成Auth路由和认证模块.跟着代码往下解读. php artisan make:auth // Http/Controllers/Auth/Login ...
- MapReduce计数程序(自主复习)
1.MyWordCount类 注意: 1.本机+测试,两个注释都放开 2.本机跑集群,要开异构平台为true 3.集群跑,把两个注释都注起来,然后在集群上面跑 package com.littlepa ...
- 循环 for 读取文件
cat filename(待读取的文件) | while read line do echo $line done
- linux tar压缩解压命令的详细解释
tar [-cxtzjvfpPN] 文件与目录 参数:-c :建立一个压缩文件的参数指令(create 的意思):-x :解开一个压缩文件的参数指令!-t :查看 tarfile 里面的文件!特别注意 ...