POJ 2104 - 主席树 / 询问莫队+权值分块
题目大意应该都清楚。
今天看到一篇博客用分块+莫对做了这道题,直接惊呆了。
首先常规地离散化后将询问分块,对于某一询问,将莫队指针移动到指定区间,移动的同时处理权值分块的数字出现次数(单独、整块),莫队完后,现在的权值分块就是关于当前区间的。然后再从左到右扫描分块,直到数字个数+该块个数>=k,这时进入该块逐个加,当数字个数>=k时,直接跳出输出离散化之前的数字。
试了很多种块的大小,最后还是选择sqrt(100000) ≈ 320,时间比我的主席树还少(肯定是我写的丑)。
code
1040ms
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
const int N = 1e5 + 5, M = 5e3 + 5, S = 320;
int n, m;
int val[N], b[N], len, cnt[S], num_cnt[N], ans[M];
struct QRY{
int x, y, k, mo_bl, id;
inline bool operator < (const QRY &b) const{
return mo_bl < b.mo_bl || (mo_bl == b.mo_bl && y < b.y);
}
}qry[M];
int head, tail;
namespace IO{
inline int read(){
int i = 0, f = 1; char ch = getchar();
for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
if(ch == '-') f = -1, ch = getchar();
for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
return i * f;
}
inline void wr(int x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) wr(x / 10);
putchar(x % 10 + '0');
}
}using namespace IO;
inline void disc_init(){
sort(b + 1, b + len + 1);
len = unique(b + 1, b + len + 1) - b - 1;
for(int i = 1; i <= n; i++) val[i] = lower_bound(b + 1, b + len + 1, val[i]) - b;
}
inline void handleMo(int l, int r){
while(head < l){
int part_bl = val[head] / S + (val[head] % S ? 1 : 0);
cnt[part_bl]--;
num_cnt[val[head]]--;
head++;
}
while(head > l){
head--;
int part_bl = val[head] / S + (val[head] % S ? 1 : 0);
cnt[part_bl]++;
num_cnt[val[head]]++;
}
while(tail < r){
tail++;
int part_bl = val[tail] / S + (val[tail] % S ? 1 : 0);
cnt[part_bl]++;
num_cnt[val[tail]]++;
}
while(tail > r){
int part_bl = val[tail] / S + (val[tail] % S ? 1 : 0);
cnt[part_bl]--;
num_cnt[val[tail]]--;
tail--;
}
}
int main(){
freopen("h.in", "r", stdin);
n = read(), m = read();
for(int i = 1; i <= n; i++) val[i] = b[++len] = read();
disc_init();
for(int i = 1; i <= m; i++){
int x = read(), y = read(), k = read(), bl = x / S + (x % S ? 1 : 0);
qry[i] = (QRY){x, y, k, bl, i};
}
sort(qry + 1, qry + m + 1);
head = tail = 0;
for(int i = 1; i <= m; i++){
int l = qry[i].x, r = qry[i].y, k = qry[i].k, sum = 0;
handleMo(l, r);
int now = 1;
try{
while(sum + cnt[now] < k) sum += cnt[now++];
for(int j = (now - 1) * S + 1; j <= min(n, now * S); j++)
if(sum + num_cnt[j] < k) sum += num_cnt[j];
else throw(j);
}
catch(int x){
ans[qry[i].id] = b[x];
continue;
}
}
for(int i = 1; i <= m; i++) wr(ans[i]), putchar('\n');
return 0;
}
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 ...
- K-th Number Poj - 2104 主席树
K-th Number Poj - 2104 主席树 题意 给你n数字,然后有m次询问,询问一段区间内的第k小的数. 解题思路 这个题是限时训练做的题,我不会,看到这个题我开始是拒绝的,虽然题意清晰简 ...
- [poj 2104]主席树+静态区间第k大
题目链接:http://poj.org/problem?id=2104 主席树入门题目,主席树其实就是可持久化权值线段树,rt[i]维护了前i个数中第i大(小)的数出现次数的信息,通过查询两棵树的差即 ...
- BZOJ 1878 [SDOI2009]HH的项链 (主席树 或 莫队算法)
题目链接 HH的项链 这道题可以直接上主席树的模板 #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) ...
- poj 2104 主席树(区间第k大)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 44940 Accepted: 14946 Ca ...
- POJ 2104 主席树模板题
#include <iostream> #include <cstdio> #include <algorithm> int const maxn = 200010 ...
- 【莫队算法】【权值分块】bzoj2223 [Coci 2009]PATULJCI
不带修改主席树裸题<=>莫队+权值分块裸题. 复杂度O(m*sqrt(n)). P.S.题目描述坑爹,第二个数是权值的范围. #include<cstdio> #include ...
- 【带修莫队】【权值分块】bzoj3196 Tyvj 1730 二逼平衡树
这题用了三种算法写: 分块+二分:O(n*sqrt(n*log(n)) 函数式权值分块:O(n*sqrt(n)) 带修莫队+权值分块:O(n5/3) 结果……复杂度越高的实际上跑得越快……最后这个竟然 ...
随机推荐
- 日历控件input框默认显示当日日期
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script sr ...
- java中volatile关键字的含义--volatile并不能做到线程安全
在Java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...
- Altium Designer四层板起步
参考转自:https://www.cnblogs.com/raymon-tec/p/5631318.html 双层板:一个是Top layer,一个是Bottom layer,layer层是信号层,也 ...
- 芯片TPS70925
TPS70925电源芯片 从上图中可以看出EN脚是使能脚,并且是高使能,低失能. tps70925的典型用法: 这个芯片有很多封装,我们用的是第一个:
- 常用的Windows命令
常用的Windows命令 explorer-------打开资源管理器 logoff---------注销命令 shutdown-------关机命令 lusrmgr.msc----本机用户和组 se ...
- Javascript和jquery事件--鼠标事件的小结
1.鼠标事件的主要事件应该是mouseup, mousedown, mousewheel, mousemove, mouseover, moveout. <1>其中mouseup和mous ...
- 用CSS实现阴阳八卦图等图形
CSS还是比较强大的,可以实现中国古典的"阴阳八卦图"等形状. 正方形 #rectangle { width: 200px; height: 100px; backgrount-c ...
- ANDROID内存优化(大汇总——全)
写在最前: 本文的思路主要借鉴了2014年AnDevCon开发者大会的一个演讲PPT,加上把网上搜集的各种内存零散知识点进行汇总.挑选.简化后整理而成. 所以我将本文定义为一个工具类的文章,如果你在A ...
- 从Set里面取出有序的记录
Set里面的记录是无序的.假设想使用Set,然后又想里面的记录是有序的,就能够使用TreeSet.而不是HashSet.在使用TreeSet的时候,里面的元素必须是实现了Comparable接口的,T ...
- swift学习第六天:数组
数组 数组的介绍 数组(Array)是一串有序的由相同类型元素构成的集合 数组中的集合元素是有序的,可以重复出现 Swift中的数组 swift数组类型是Array,是一个泛型集合 数组的初始化 数组 ...