poj2104

题意

给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数。

分析

划分树模板,O(mlogn)。

  1. 建树。根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右子树(在子区间内数与数的相对位置保持不变),递归向下分割。
  2. 查询。toleft[p][i] 表示第 p 层前 i 个数中有多少个整数分入下一层。查询最重要的是确定新的查询区间,若递归查询左区间,则新的子区间的左边一定是上一层区间 [L, l - 1] 里的 toleft[dep][l-1] - toleft[dep][L-1] 个整数,那么 newl = L + toleft[dep][l-1] - toleft[dep][L-1],[l, r] 区间内有cnt = toleft[dep][r] - toleft[dep][l - 1] 个数,所以 newr = newl + cnt - 1;查询右区间则要先确定 newr 的值,[r+1, R] 中有 c = toleft[dep][R] - toleft[dep][r] 个整数位于左子区间的右方,所以查询区间 r 要向右移 c 个数,newr = r + c,newl = newr - (r - l - cnt)。

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int INF = 1e9;
const int MAXN = 1e5 + 5;
const int LOG_N = 30;
// tree[dep][i] 第dep层第i个位置的数值
int tree[LOG_N][MAXN];
int sorted[MAXN];
// toleft[p][i] 第p层前i个数中有多少个整数分入下一层
int toleft[LOG_N][MAXN]; void build(int l, int r, int dep)
{
if(l == r) return;
int mid = (l + r) / 2;
int same = mid - l + 1; // 和中点数相同的数的个数
for(int i = l; i <= r; i++)
if(tree[dep][i] < sorted[mid]) same--;
int lpos = l, rpos = mid + 1;
for(int i = l; i <= r; i++)
{
if(tree[dep][i] < sorted[mid])
tree[dep + 1][lpos++] = tree[dep][i];
else if(tree[dep][i] == sorted[mid] && same)
{
tree[dep + 1][lpos++] = tree[dep][i];
same--;
}
else tree[dep + 1][rpos++] = tree[dep][i];
toleft[dep][i] = toleft[dep][l - 1] + lpos - l;
}
build(l, mid, dep + 1);
build(mid + 1, r, dep + 1);
}
// [L,R]里查询子区间[l,r]第k小的数
int query(int L, int R, int l, int r, int dep, int k)
{
if(l == r) return tree[dep][l];
int mid = (L + R) / 2;
// 有多少个查询区间内的节点会进入下一层的左子树
int cnt = toleft[dep][r] - toleft[dep][l - 1];
if(cnt >= k)
{
int newl = L + toleft[dep][l - 1] - toleft[dep][L - 1];
int newr = newl + cnt - 1;
return query(L, mid, newl, newr, dep + 1, k);
}
else
{
int newr = r + toleft[dep][R] - toleft[dep][r];
int newl = newr - (r - l - cnt);
return query(mid + 1, R, newl, newr, dep + 1, k - cnt);
}
}
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m))
{
for(int i = 1; i <= n; i++)
{
scanf("%d", &sorted[i]);
tree[0][i] = sorted[i];
}
sort(sorted + 1, sorted + n + 1);
build(1, n, 0);
while(m--)
{
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
printf("%d\n", query(1, n, l, r, 0, k));
}
}
return 0;
}

poj2104(划分树模板)的更多相关文章

  1. poj2104(划分树模板)

    poj2104 题意 给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数. 分析 划分树模板,O(mlogn). 建树.根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右 ...

  2. hdu2665 && poj2104划分树

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 47066   Accepted: 15743 Ca ...

  3. hdu 2665 Kth number(划分树模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=2665 [ poj 2104 2761 ]  改变一下输入就可以过 http://poj.org/problem? ...

  4. HDU-3743 Minimum Sum,划分树模板

    Minimum Sum 被这个题坑了一下午,原来只需找一个最中间的数即可,我以为是平均数. 题意:找一个数使得这个数和区间内所有数的差的绝对值最小.输出最小值. 开始用线段树来了一发果断T了,然后各种 ...

  5. VIJOS P1081 野生动物园 SBT、划分树模板

    [描述] cjBBteam拥有一个很大的野生动物园.这个动物园坐落在一个狭长的山谷内,这个区域从南到北被划分成N个区域,每个区域都饲养着一头狮子.这些狮子从北到南编号为1,2,3,…,N.每头狮子都有 ...

  6. poj2104 划分树 区间K大 在线 无修改

    博主sbit....对于高级数据结构深感无力,然后这些东西在OI竟然烂大街了,不搞就整个人都不好了呢. 于是我勇猛的跳进了这个大坑 ——sbit 区间K大的裸题,在线,无修改. 可以用归并树(\(O( ...

  7. poj 2104 (划分树模板)

    Description You are working for Macrohard company in data structures department. After failing your ...

  8. POJ2104 K-th Number 划分树 模板题啊

    /*Source Code Problem: 2104 User: 96655 Memory: 14808K Time: 1282MS Language: G++ Result: Accepted S ...

  9. poj2104 主席树模板题

    题意 给出n个数字组成的数字序列,有m组询问.每次询问包含三个数字l,r,k.对于每个询问输出序列区间[l,r]中第k大的数字. 分析 这是主席树的模板题,套板子就可以 #include <cs ...

随机推荐

  1. SQL语句简单整理

    转载原文:http://blog.sina.com.cn/s/blog_48df31d901017c6o.html 1.用户 - 查看当前用户的缺省表空间 select username,defaul ...

  2. file_get_contents HTTP request failed! Internal Server Error

    使用file_get_contents报错 Severity: WarningMessage: file_get_contents(http://geetest.com:8000/select?gid ...

  3. Swift中枚举的总结以及使用

    枚举定义了一组具有相关性的数据,是开发者可以再带吗中以一个安全的方式来使用这些值,以又助于提供代码的可读性. 在Swift中,枚举可以分成两种:任意类型的枚举和指定类型的枚举,结构如下: //任意类型 ...

  4. Vue 事件驱动和依赖追踪

    之前关于 Vue 数据绑定原理的一点分析,最近需要回顾,就顺便发到随笔上了 在之前实现一个自己的Mvvm中,用 setter 来观测model,将界面上所有的 viewModel 绑定到 model ...

  5. [bug] Cannot proceed because system tables used by Event Scheduler were found damaged at server start

    本地:mac 10.12.3  mysql 5.6 远程:linux 7.3    mysql 5.7.18.  (远程数据库yum安装,又5.6升级到5.7) 步骤:从本地数据库导出数据到远程数据库 ...

  6. 使用EzHttp框架 开发基于HTTP协议的CS轻应用

    框架概述 EzHttp是临时起意构思和开发的一个框架,目的在于简化CS轻应用开发过程.开发语言是C#. 普通的基于HTTP的应用开发基本上是RESTful的,客户端调用封装需要人工写代码,就算利用三方 ...

  7. 深入tornado中的Configurable

    Configurable十分重要! 位于tornado.util文件中,它是一个工厂类. 我们暂且称这个类为 配置类 . 我们暂且约定:该类的子类称之为 直属配置子类 , 该类的孙类.重孙类……称之为 ...

  8. Javascript使用克隆的原型模式

    ECMAScript 5中提供了Object.create()方法. 使用这个方法很容易克隆一个一模一样的对象. var animal=function(){ this.blood=100; this ...

  9. 表单提交音乐文件(php)

    利用点空闲时间来写个博客,最近做的项目中需要表单提交音频的,图片的,各种类型,把它存到数据库里,这里先来说一下音乐文件的表单提交吧,后几天再来更新输入数据库的,先看一下效果 点击浏览 就会出来预览,点 ...

  10. bzoj1798 [Ahoi2009]维护序列

    Description 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2 ...