poj 2104(线段树)
| Time Limit: 20000MS | Memory Limit: 65536K | |
| Total Submissions: 45653 | Accepted: 15177 | |
| Case Time Limit: 2000MS | ||
Description
That is, given an array a[1...n] of different integer numbers, your
program must answer a series of questions Q(i, j, k) in the form: "What
would be the k-th number in a[i...j] segment, if this segment was
sorted?"
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the
question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort
this segment, we get (2, 3, 5, 6), the third number is 5, and therefore
the answer to the question is 5.
Input
first line of the input file contains n --- the size of the array, and m
--- the number of questions to answer (1 <= n <= 100 000, 1 <=
m <= 5 000).
The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given.
The following m lines contain question descriptions, each
description consists of three numbers: i, j, and k (1 <= i <= j
<= n, 1 <= k <= j - i + 1) and represents the question Q(i, j,
k).
Output
Sample Input
7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3
Sample Output
5
6
3
转自:http://blog.csdn.net/famousdt/article/details/7064866
建树的过程比较简单,对于区间[l,r],首先通过对原数组的排序找到这个区间的中位数a[mid],小于a[mid]的数划入它的左子树[l,mid-1],大于它的划入右子树[mid,r]。
同时,对于第i个数a[i],记录在[l,i]区间内有多少数被划入左子树。最后,对它的左子树区间[l,mid-1]和右子树区间[mid,r]递归的继续建树就可以了。
建树的时候要注意,对于被分到同一子树的元素,元素间的相对位置不能改变。
查找的过程中主要问题就是确定将要查找的区间。
查找深度为dep,在大区间[L ,R]中找小区间[l ,r]中的第k元素。
我们的想法是,先判断[l ,r]中第k元素在[L ,R]的哪个子树中,然后找出对应的小区间和k,递归的进行查找,直到小区间的l==r为止。
通过之前的记录可以知道,在区间[L,l-1]中有(toleft[dep][l-1]-toleft[dep][L-1])进入左子树,
记它为x。
同理区间[L,r]中有(toleft[dep][r]-toleft[dep][L-1])个数进去左子树,记它为y。
所以,我们知道区间小区间[l,r]中有(y-x)个数进入左子树。那么如果(y-x)>=k,那么就在左子树中继续查找,否则就在右子树中继续查找。
接着,解决查找的小区间的问题。
如果接下来要查找的是左子树,那么小区间应该是[L+([L,l-1]区间进入左子树的个数),L+([L,r]区间内进入左子树的个数)-1]。即区间[L+x,L+y-1]。(这里的-1应该是防止边界问题)
显然,这里k不用变。
如果接下来要查找的是右子树,那么小区间应该是[mid+([L,l-1]区间中进入右子树的个数),mid+([L,r]区间进入右子树的个数)-1]。
即区间[mid+(l-L-x),mid+(r-L-y)]。(这里要记得+1)
显然,这里k要减去区间里已经进入左子树的个数,即k变为k-(y-x)。
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAXSIZE = ;
int tree[][MAXSIZE]; ///树最多也就30层
int _sort[MAXSIZE];
int toleft[][MAXSIZE]; void build(int l,int r,int deep)
{
if(l==r) return;
int mid =(l+r)>>;
int same = mid-l+; ///设这个变量的主要原因是判断tree[deep][i]==_sort[mid]时tree[deep][i]往哪边走
for(int i=l; i<=r; i++)///计算放于左子树中与中位数相等的数字个数,
{
// printf("%d ",tree[deep][i]);
if(tree[deep][i]<_sort[mid]) same--;
}
//printf("\n");
int left = l;
int right = mid+;
for(int i=l; i<=r; i++)
{
int flag = ;
if((tree[deep][i]<_sort[mid])||(tree[deep][i]==_sort[mid]&&same>))
{
flag = ;
tree[deep+][left++] = tree[deep][i];
if(tree[deep][i]==_sort[mid]) same--;
}
else
{
tree[deep+][right++] = tree[deep][i];
}
toleft[deep][i] = toleft[deep][i-]+flag;
}
build(l,mid,deep+);
build(mid+,r,deep+);
} int query(int L,int R,int l,int r,int k,int deep)
{
if(l==r) return tree[deep][l];
int x = toleft[deep][l-]-toleft[deep][L-]; ///x代表[L,l-1]区间内进入左子树的数字的量
int y = toleft[deep][r]- toleft[deep][L-]; ///y代表[L,r]区间内进入左子树的数字的量
int cnt = y-x; ///cnt代表[l,r]区间内进入左子树的数字的量
int mid = (L+R)>>;
int rx = l - L - x;///l左边放在右子树中的数字个数
int ry = r - L - y;///到r右边为止位于右子树的数字个数
if(cnt>=k)
{
query(L,mid,L+x,L+y-,k,deep+);
}else{
query(mid+,R,mid+rx+,mid+ry+,k-cnt,deep+);
} }
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{ memset(toleft,,sizeof(toleft));
for(int i=; i<=n; i++)
{
scanf("%d",&_sort[i]);
tree[][i] = _sort[i];
} sort(_sort+,_sort+n+);
build(,n,);
while(m--)
{
int a,b,k;
scanf("%d%d%d",&a,&b,&k);
int t = query(,n,a,b,k,);
printf("%d\n",t);
}
}
return ;
}
poj 2104(线段树)的更多相关文章
- K-th Number Poj - 2104 主席树
K-th Number Poj - 2104 主席树 题意 给你n数字,然后有m次询问,询问一段区间内的第k小的数. 解题思路 这个题是限时训练做的题,我不会,看到这个题我开始是拒绝的,虽然题意清晰简 ...
- poj 2886 线段树+反素数
Who Gets the Most Candies? Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 12744 Acc ...
- [poj 2104]主席树+静态区间第k大
题目链接:http://poj.org/problem?id=2104 主席树入门题目,主席树其实就是可持久化权值线段树,rt[i]维护了前i个数中第i大(小)的数出现次数的信息,通过查询两棵树的差即 ...
- K-th Number POJ - 2104 划分树
K-th Number You are working for Macrohard company in data structures department. After failing your ...
- poj 3468(线段树)
http://poj.org/problem?id=3468 题意:给n个数字,从A1 …………An m次命令,Q是查询,查询a到b的区间和,c是更新,从a到b每个值都增加x.思路:这是一个很明显的线 ...
- POJ——3264线段树
题目: 输入两个数(m,n),m表示牛的头数,n表示查询的个数.查询时输入两个数(x,y),表示查询范围的起始值和终止值,查询结果是,这个区间内牛重量的最大值减去牛重量的最小值,数量级为1000,00 ...
- POJ 2828 线段树(想法)
Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 15422 Accepted: 7684 Desc ...
- poj 2828 线段树
http://poj.org/problem?id=2828 学到的思维: 1.变化的或者后来的优先影响前面的,那么从最后一个往前看,最后一个就成了 确定的, 而且后来的也能够确定----假设从前往后 ...
- POJ - 1177 线段树
POJ - 1177 扫描线 这道题也算是一道扫描线的经典题目了. 只不过这道题是算周长,非常有意思的一道题.我们已经知道了,一般求面积并,是如何求的,现在我们要把扫描线进行改造一下,使得能算周长. ...
- poj 2886 (线段树+反素数打表) Who Gets the Most Candies?
http://poj.org/problem?id=2886 一群孩子从编号1到n按顺时针的方向围成一个圆,每个孩子手中卡片上有一个数字,首先是编号为k的孩子出去,如果他手上的数字m是正数,那么从他左 ...
随机推荐
- bzoj3694: 最短路(树链剖分/并查集)
bzoj1576的帮我们跑好最短路版本23333(双倍经验!嘿嘿嘿 这题可以用树链剖分或并查集写.树链剖分非常显然,并查集的写法比较妙,涨了个姿势,原来并查集的路径压缩还能这么用... 首先对于不在最 ...
- VS 2013 with update安装失败(kb2829760)解决方案
update过程中遇到kb2829760补丁无法更新而导致vs安装失败的解决方法: 1.安装KB2829760: 2.安装KB2829760中文语言包: 3.安装VS2013 with update. ...
- C++之内部类与外部类(嵌套类)及友元
转载于:http://www.cnblogs.com/qzhforthelife/p/3226885.html 先上代码: class Outer { public: Outer(){m_outerI ...
- HDU1083 :Courses(二分图匹配)
Cources Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- G. Trace ACM-ICPC 2018 徐州赛区网络预赛 线段树写法
There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xx , yy ...
- 组合框控件 -- CComboBox
组合框控件 -- CComboBox 组合框其实就是把一个编辑框和一个列表框组合到了一起,分为三种:简易(Simple)组合框.下拉式(Dropdown)组合框和下拉列表式(Drop List)组合框 ...
- arm架构与体系结构
1.cpu与soc 内核版本号与soc版本号由arm公司确定. 芯片型号由各半导体公司确定. soc包括cpu与一些基本内设.(一般提到CPU都指的是soc,实际上cpu只是soc的一部分). RIS ...
- MyBatis框架的使用及源码分析(十) CacheExecutor,SimpleExecutor,BatchExecutor ,ReuseExecutor
Executor分成两大类,一类是CacheExecutor,另一类是普通Executor. 普通类又分为: ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情.它为每个语句的执行 ...
- c# 自定义排序Compare
.net FrameWork 框架博大精深,用着忘着,计划对自己能够想到知识点梳理一下,此篇是对自定义排序的理解: class Program { static void Main(string[] ...
- list互转datatable 支持Nullable转换
/// <summary> /// list转datatable /// </summary> /// <param name="list">& ...