题目大意:
  给你一个长度为$n(n\le40000)$的数列$\{a_i\}(1\le a_i\le n)$,给出$m(m\le40000)$次询问,每次给出$l,r,k_1,k_2$询问区间$[l,r]$中出现次数第$k_1$小的数中第$k_2$小的数是多少?

思路:
  运用莫队算法离线处理所有询问,分块维护数列中每个数的出现次数。考虑如何维护出现次数的出现次数以及出现次数相同的数。同样采用分块,先预处理出对于某一种出现次数,所有可能的数,再将其离散化,对于离散化后的数分块维护。由于题目空间限制只有24M,因此需要手写内存池或者使用vector,可以证明离散化以后的数组空间复杂度是$O(n)$的。这样时间复杂度$O(m\sqrt n)$,空间复杂度是$O(n+m)$。

 #include<cmath>
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int N=,M=;
int n,a[N],b[N],block,ans[M],cnt[N];
struct Query {
int l,r,k1,k2,id;
bool operator < (const Query &another) const {
return l/block<another.l/block||(l/block==another.l/block&&r<another.r);
}
};
Query q[M];
std::vector<int> v[N],rank[N],cnt1,sum1,cnt2[N],sum2[N];
inline void modify(const int &x,const int &p,const int &d) {
cnt2[x][p]+=d;
sum2[x][p/block]+=d;
if(d==&&!cnt1[x]++) sum1[x/block]++;
if(d==-&&!--cnt1[x]) sum1[x/block]--;
}
inline void modify(const int &x,const int &d) {
if(cnt[x]) modify(cnt[x],rank[x][cnt[x]],-);
if(cnt[x]+=d) modify(cnt[x],rank[x][cnt[x]],);
}
inline int solve(const std::vector<int> &c,const std::vector<int> &s,const int &k) {
register int x=,cnt=;
while((cnt+s[x])<k) cnt+=s[x++];
for(register int i=x*block;i<(x+)*block;i++) {
if((cnt+=!!c[i])>=k) return i;
}
}
inline int query(const int &k1,const int &k2) {
const int x=solve(cnt1,sum1,k1);
return v[x][solve(cnt2[x],sum2[x],k2)];
}
int main() {
block=sqrt(n=getint());
for(register int i=;i<=n;i++) {
cnt[a[i]=b[i]=getint()]++;
}
std::sort(&b[],&b[n]+);
for(register int i=;i<=n;i++) {
if(b[i]==b[i-]) continue;
rank[b[i]].resize(cnt[b[i]]+);
for(register int j=;j<=cnt[b[i]];j++) {
rank[b[i]][j]=v[j].size();
v[j].push_back(b[i]);
}
cnt[b[i]]=;
}
for(register int i=;i<=n;i++) {
cnt2[i].resize(v[i].size()+);
sum2[i].resize(cnt2[i].size()/block+);
}
const int m=getint();
for(register int i=;i<m;i++) {
const int l=getint(),r=getint(),k1=getint(),k2=getint();
q[i]=(Query){l,r,k1,k2,i};
}
cnt1.resize(n+);
sum1.resize(n/block+);
std::sort(&q[],&q[m]);
for(register int i=,l=,r=;i<m;i++) {
while(r<q[i].r) modify(a[++r],);
while(l>q[i].l) modify(a[--l],);
while(r>q[i].r) modify(a[r--],-);
while(l<q[i].l) modify(a[l++],-);
ans[q[i].id]=query(q[i].k1,q[i].k2);
}
for(register int i=;i<m;i++) {
printf("%d\n",ans[i]);
}
return ;
}

[BZOJ3920]Yuuna的礼物的更多相关文章

  1. bzoj3920: Yuuna的礼物(莫队+分块套分块)

    思路挺简单的,但是总感觉好难写...码力还是差劲,最后写出来也挺丑的 这题显然是个莫队题,考虑怎么转移和询问... 根据莫队修改多查询少的特点,一般用修改快查询慢的分块来维护.查第$k_1$小的出现次 ...

  2. 【莫队算法】【权值分块】bzoj3920 Yuuna的礼物

    [算法一] 暴力. 可以通过第0.1号测试点. 预计得分:20分. [算法二] 经典问题:区间众数,数据范围也不是很大,因此我们可以: ①分块,离散化,预处理出: <1>前i块中x出现的次 ...

  3. bzoj 3920: Yuuna的礼物

    Description 转眼就要到Karin的生日了!Yuuna她们想为她准备生日礼物!现在有许多礼物被排列成了一个一维序列,每个礼物都有一个价值.Yuuna对这个序列十分感兴趣.因此,你需要多次回答 ...

  4. BZOJ.3920.Yuuna的礼物(莫队 分块套分块 分段离散化)

    题目链接 详细题解:https://www.cnblogs.com/autsky-jadek/p/4376091.html 代码参考自:https://www.cnblogs.com/Sakits/p ...

  5. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  6. jQuery动画-圣诞节礼物

    ▓▓▓▓▓▓ 大致介绍 下午看到了一个送圣诞礼物的小动画,正好要快到圣诞节了,就动手模仿并改进了一些小问题 原地址:花式轮播----圣诞礼物传送 思路:动画中一共有五个礼物,他们平均分布在屏幕中,设置 ...

  7. bzoj 3055礼物运送 floyed + 状压DP

    bzoj 3055: 礼物运送 floyed first 设f[i][S]表示取到了S集合中的所有点(不一定是经过的所有点),最后停在了i的最优值. 初始就f[i][{i}] = dis[1][i] ...

  8. Typecast 免费了!献给设计师们的礼物

    TypeCast 让你可以从 Fonts.com.TypeKit.FontDeck 和 Google 这些字体供应和商选择字体,而且能非常方便的比较这些字体使用效果.如果你想获得用户对这些字体效果的反 ...

  9. 【HDU 5835】Danganronpa(分配礼物)

    10种礼物,每种有ai个,每个小朋友分两个礼物,其中普通礼物要求相邻两人的不能一样,求最多分给几个小朋友. sum/2是最多的情况.什么时候发不了那么多,就是当max很大,无论怎么发,都发不完max. ...

随机推荐

  1. java 日期处理相关

    /** *获取指定日期 前后指定天数的 日期 * */ public static String getNewDate(String sdate, int days) throws Exception ...

  2. Jtag To Axi4 debug 读写寄存器的tcl脚本封装

    把下列代码保存为.tcl或者.txt文本保存在某个路径下 打开vivado,在tcl concle中输入 “source 文件路径”,将脚本加载至工具中后, 例如读寄存器地址32'h12345678的 ...

  3. 云效(阿里云)流水线 + nginx + uWsgi + flask + python3 基础环境搭建 --备忘

    一.开发环境搭建 1.安装python3 yum -y groupinstall "Development tools" yum -y install zlib-devel bzi ...

  4. 有向图强连通分量Tarjan算法

    在https://www.byvoid.com/zhs/blog/scc-tarjan中关于Tarjan算法的描述非常好,转述如下: 首先解释几个概念: 有向图强连通分量:在有向图G中,如果两个顶点间 ...

  5. 软考——(1)J2SE

    我们先从Java说起,简单的说,Java是一种面向对象的程序设计语言,可跨平台使用. 与之前学习的程序设计语言相比,最值得一提的就是Java的两种核心机制:Java虚拟机和垃圾回收机制. 1)虚拟机 ...

  6. BZOJ - 2728 与非

    题意: 给定N个数,一个数k和一个范围[L,R].每个数可以使用任意次,k表示与非不超过k位.求出范围内有多少个数可以由他们的与非和表示. 题解: m个数进行NAND,最终的数二进制下某一位如果为1, ...

  7. BFC,IFC,GFC,FFC

    FC的全称是:Formatting Contexts,是W3C CSS2.1规范中的一个概念.它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用. ...

  8. ACMUniversity

    描述 在大学里,很多单词都是一词多义,偶尔在文章里还要用引申义.这困扰Redraiment很长的时间. 他开始搜集那些单词的所有意义.他发现了一些规律,例如 “a”能用“e”来代替, “c”能用“f” ...

  9. 《c程序设计语言》读书笔记-递归实现快速排序算法

    #include <stdio.h> void swap(int v[],int i,int j) { int temp; temp = v[i]; v[i] = v[j]; v[j] = ...

  10. HDU1541 经典树状数组

    HDU1541 题意: 如图,等级为0的点有1,等级为1得点有4,2  等级为2的点有3,等级为3的点有5-------即即左下角的点的个数 现给你一些点(x,y),输入顺序按y升序,y相等时按x升序 ...