SPOJ--K-query (线段树离线) 离线操作解决一些问题
Given a sequence of n numbers a1, a2, ..., an and a number of k- queries. A k-query is a triple (i, j, k) (1 ≤ i ≤ j ≤ n). For each k-query (i, j, k), you have to return the number of elements greater than k in the subsequence ai, ai+1, ..., aj.
Input
- Line 1: n (1 ≤ n ≤ 30000).
- Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 109).
- Line 3: q (1 ≤ q ≤ 200000), the number of k- queries.
- In the next q lines, each line contains 3 numbers i, j, k representing a k-query (1 ≤ i ≤ j ≤ n, 1 ≤ k ≤ 109).
Output
- For each k-query (i, j, k), print the number of elements greater than k in the subsequence ai, ai+1, ..., aj in a single line.
Example
Input
5
5 1 2 3 4
3
2 4 1
4 4 4
1 5 2 Output
2
0
3 题意:给定 一个数组, q次询问, 每次询问区间[L, R]内大于k的数字有多少个。 这题算是比较老比较水的题目了, 但是感觉 离线可以处理 很多 大量询问的问题。 其中思想很值得挖掘学习。
比如这题,先考虑线段树,这棵线段树的叶子都是1, 先把 所有询问按k的大小从小到大排序, 然后对于 每个询问可以把 小于当前询问k的数字的位置在线段树里置0,那么结果就是线段树的区间 求和问题来了。 这样Q次询问, 最终所有数字都加进来了 复杂度 并不高 O( N + Q * log N)
const int MAXN = 3e4+;
const int MAXQ = 2e5+;
struct Node{
int L, R, k, idx;
Node (int L = , int R = , int k = , int idx = ):
L(L), R(R), k(k), idx(idx){}
bool operator < (const Node &rhs)const{
return k < rhs.k;
}
}Q[MAXQ];
int sum[MAXN << ];
void build (int l, int r, int pos){
if (l == r){
sum[pos] = ;
return;
}
int mid = (l + r) >> ;
build(l, mid, pos<<);
build(mid+, r, pos<<|);
sum[pos] = sum[pos<<] + sum[pos<<|];
}
void update (int l, int r, int pos, int x, int val){
if (l == r){
sum[pos] = val;
return;
}
int mid = (l + r) >> ;
if (x <= mid){
update(l, mid, pos<<, x, val);
}else{
update(mid+, r, pos<<|, x, val);
}
sum[pos] = sum[pos<<] + sum[pos<<|];
}
int query (int l, int r, int pos, int ua, int ub){
if (ua <= l && ub >= r){
return sum[pos];
}
int mid = (l + r) >> ;
int res = ;
if (ua <mid){
res += query(l, mid, pos<<, ua, ub);
}
if (ub > mid){
res += query(mid+, r, pos<<|, ua, ub);
}
return res;
}
int ans[MAXQ], IDX[MAXN], val[MAXN];
bool cmp(int i, int j){
return val[i] < val[j];
}
int main() { int n, q;
while (~ scanf ("%d", &n)){
for (int i = ; i < n; i++){
scanf ("%d", val+i);
IDX[i] = i;
}
sort (IDX, IDX+n, cmp);
scanf ("%d", &q);
for (int i = ; i < q; i++){
int ua, ub, k;
scanf ("%d%d%d", &ua, &ub, &k);
Q[i] = Node(ua, ub, k, i);
}
sort (Q, Q+q);
build(, n, );
int p = ;
for (int i = ; i < q; i++){
while (p < n && val[IDX[p]] <= Q[i].k){
update(, n, , IDX[p]+, );
p++;
}
ans[Q[i].idx] = query(, n, , Q[i].L, Q[i].R);
}
for (int i = ; i < q; i++){
printf("%d\n", ans[i]);
}
}
return ;
}
再来看15年编程之美复赛的一道题。
你正在和小冰玩一个猜数字的游戏。小冰首先生成一个长为N的整数序列A1, A2, …, AN。在每一轮游戏中,小冰会给出一个区间范围[L, R],然后你要猜一个数K。如果K在AL, AL+1, …, AR中,那么你获胜。
在尝试了几轮之后,你发现这个游戏太难(无聊)了。小冰决定给你一些提示,你每猜一次,小冰会告诉你K与AL, AL+1, …, AR中最接近的数的绝对差值,即min(|Ai - K|), L ≤ i ≤ R。
也是一个数组,多次询问,每次求区间内与k最接近的数字。
这题 可以可持久化线段树做, 但是代码量大, 除此之外还可以 离线+线段树, 最接近k的值 要么比k小 要么比k大。
先考虑比k小的时候, 首先 把 所有数字和询问放到一起排序,按值排序, 把询问和数字 分开, 然后 从小到大加入到线段树, 那么对于某次询问[L, R]此时线段树的区间[L, R]最大值就是比k小的最接近的k的值, 同理可以求出比k大的最接近k的值。然后两者比较即可。 代码略。
SPOJ--K-query (线段树离线) 离线操作解决一些问题的更多相关文章
- 线段树+离线 hdu5654 xiaoxin and his watermelon candy
传送门:点击打开链接 题意:一个三元组假设满足j=i+1,k=j+1,ai<=aj<=ak,那么就好的.如今告诉你序列.然后Q次询问.每次询问一个区间[l,r],问区间里有多少个三元组满足 ...
- HDU 4417 【线段树+离线处理】
http://acm.hdu.edu.cn/showproblem.php?pid=4417 题意:找出给定区间内,有多少个数小于等于给定的数.用线段树维护的话会超时,要用到线段树的离线操作,对询问与 ...
- 牛客练习赛53 E-老瞎眼pk小鲜肉(思维+线段树+离线)
前言 听说是线段树离线查询?? 做题做着做着慢慢对离线操作有点感觉了,不过也还没参透,等再做些题目再来讨论离线.在线操作. 这题赛后看代码发现有人用的树状数组,$tql$.当然能用树状数组写的线段树也 ...
- query 线段树 + 区间排序
https://nanti.jisuanke.com/t/41391 这个题目没有很难想,比较暴力,但是要会算复杂度,不会算复杂度,就会觉得自己的算法会超时,实际上不会. 这个题目就是直接暴力求出每一 ...
- HDU 3333 Turing Tree 线段树+离线处理
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...
- 【HDU4630 No Pain No Game】 dp思想+线段树的离线操作
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4630 题意:给你n个数据范围在[1,n]中的数,m个操作,每个操作一个询问[L,R],让你求区间[L, ...
- lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs 倍增
https://www.luogu.org/problemnew/show/P3379 1.欧拉序+rmq(st) /* 在这里,对于一个数,选择最左边的 选择任意一个都可以,[left_index, ...
- 51nod 1463 找朋友(线段树+离线处理)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463 题意: 思路: 好题! 先对所有查询进行离线处理,按照右区间排序, ...
- HDU4417 线段树 + 离线处理
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 , 线段树(或树状数组) + 离线处理 最近看了几道线段树的题都是需要离线处理数据的,正好这块比 ...
随机推荐
- 【转】Android onTouch()和onTouchEvent()区别
1.onTouch()方法: onTouch方式是View的OnTouchListener接口中定义的方法. 当一个View绑定了OnTouchListener后,当有Touch事件触发时,就会调用o ...
- Machine Learning—Mixtures of Gaussians and the EM algorithm
印象笔记同步分享:Machine Learning-Mixtures of Gaussians and the EM algorithm
- Robotium API -- click/clickLong操作
click&clickLong方法(点击/长按事件) ArrayList<android.widget.TextView> clickList(int ...
- ViewPager 详解(二)---详解四大函数
前言:上篇中我们讲解了如何快速实现了一个滑动页面,但问题在于,PageAdapter必须要重写的四个函数,它们都各有什么意义,在上节的函数内部为什么要这么实现,下面我们就结合Android的API说明 ...
- MySQL定时备份之使用Linux下的crontab定时备份实例
这篇文章主要介绍了使用Linux下的crontab进行MySQL定时备份的例子,需要的朋友可以参考下 复制代码代码如下: ##################################### ...
- [转] gdb中忽略信号处理
信号(Signals) 信号是一种软中断,是一种处理异步事件的方法.一般来说,操作系统都支持许多信号.尤其是UNIX,比较重要应用程序一般都会处理信号.UNIX定义了许 多信号,比如SIGINT表示中 ...
- MySQL(13):Select-order by
1. 按照字段值进行排序: 语法: order by 字段 升序|降序(asc|desc) 允许多字段排序,指的是,先按照第一个字段排序,如果说,不能区分,才使用第二个字段,以此类推. ...
- Wcf+EF框架搭建实例
一.最近在使用Wcf创建数据服务,但是在和EF框架搭建数据访问时遇到了许多问题 下面是目前整理的基本框架代码,经供参考使用,源代码地址:http://git.oschina.net/tiama3798 ...
- 单点登录CAS使用记(四):为登录页面加上验证码
CAS默认的登录页面样式如下,只有用户名与密码两项验证项目. 现在需要为首页登录加上验证码功能. 第一步:首页对默认登录页面的样式进行了调整,使其看上去还算美观. 在页面上加上了验证码项目. 第二步: ...
- Qt Quick App的两种启动模式
QQmlApplicationEngine搭配Window QQuickView搭配Item 两者不同之处在于: 使用QQuickView显示QML文档,对窗口的控制权(比如设置窗口标题.Icon.窗 ...