acm
划分树toj2722
#include
<
iostream
>
#include
<
cstdio
>
#include
<
cstring
>
using
namespace
std;
#define
MAX 100005
int
tree[
20
][MAX];
//
表示每一层每个位置的值
int
sorted[MAX];
//
已排好序的序列
int
toleft[
20
][MAX];
//
表示它在一个子区间内从1到i有多少个数会被分到左边
void
build(
int
l,
int
r,
int
dep)
//
建树
{
if
(l
==
r)
return
;
int
mid,i,same,lpos,rpos;
mid
=
(l
+
r)
>>
1
;
for
(i
=
l,same
=
0
;i
<=
r;i
++
)
same
+=
(tree[dep][i]
<
sorted[mid]);
same
=
mid
-
l
+
1
-
same;
//
same表示和中间的数大小一样且会被分到左边的数的个数
for
(i
=
l,lpos
=
l,rpos
=
mid
+
1
;i
<=
r;i
++
)
{
if
(tree[dep][i]
<
sorted[mid])
//
比中间的数小,显然应该放在左边
tree[dep
+
1
][lpos
++
]
=
tree[dep][i];
else
if
(tree[dep][i]
==
sorted[mid]
&&
same)
//
和中间的数一样大,但是same不为0,即还可以放一样的,则放在左边
{
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;
//
从1到i被放在左边的数的个数
}
build(l,mid,dep
+
1
);
//
递归的去做
build(mid
+
1
,r,dep
+
1
);
}
//
查询某个区间第K大数,L,R是大区间,l和r是要查询的小区间
int
query(
int
L,
int
R,
int
l,
int
r,
int
dep,
int
k)
{
//
关键是newl和newr的计算,要仔细
if
(l
==
r)
return
tree[dep][l];
int
mid,i,newl,newr,cnt;
mid
=
(L
+
R)
>>
1
;
cnt
=
toleft[dep][r]
-
toleft[dep][l
-
1
];
if
(cnt
>=
k)
//
有大于或等于k个数倍放在左边,则上左边去找
{
//
L+在要查询的这段区间之前,这些数被放到左边几个
newl
=
L
+
toleft[dep][l
-
1
]
-
toleft[dep][L
-
1
];
//
做端点加上会被放到左边的这几个数-1,就是右端点
newr
=
newl
+
cnt
-
1
;
return
query(L,mid,newl,newr,dep
+
1
,k);
}
else
{
//
先找出右端点通过右端点得到左端点。
newr
=
r
+
toleft[dep][R]
-
toleft[dep][r];
newl
=
newr
-
(r
-
l
-
cnt);
return
query(mid
+
1
,R,newl,newr,dep
+
1
,k
-
cnt);
}
}
int
main()
{
int
n,q,i,a;
while
(scanf(
"
%d%d
"
,
&
n,
&
q)
!=
EOF)
{
memset(tree,
0
,
sizeof
(tree));
for
(i
=
1
;i
<=
n;i
++
)
{
scanf(
"
%d
"
,
&
tree[
0
][i]);
sorted[i]
=
tree[
0
][i];
}
sort(sorted
+
1
,sorted
+
n
+
1
);
build(
1
,n,
0
);
for
(i
=
0
;i
<
q;i
++
)
{
int
b,k;
scanf(
"
%d%d%d
"
,
&
a,
&
b,
&
k);
printf(
"
%d\n
"
,query(
1
,n,a,b,
0
,k));
}
}
return
0
;
}
posted on 2010-07-31 02:12
YUANZX
阅读(362)
评论(0)
编辑
收藏
引用
只有注册用户
登录
后才能发表评论。
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
网站导航:
博客园
IT新闻
BlogJava
知识库
博问
管理
Powered by:
C++博客
Copyright © YUANZX
<
2010年5月
>
日
一
二
三
四
五
六
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
导航
C++博客
首页
新随笔
联系
聚合
管理
统计
随笔 - 12
文章 - 0
评论 - 0
引用 - 0
常用链接
我的随笔
我的评论
我参与的随笔
留言簿
给我留言
查看公开留言
查看私人留言
随笔档案
2011年2月 (1)
2010年8月 (1)
2010年7月 (6)
2010年5月 (4)
搜索
最新评论
阅读排行榜
1. 并查集应用(7989)
2. 网络流(4438)
3. 暑期集训——求割点割边(1287)
4. 暑期集训——SCC(709)
5. 混合图的欧拉回路toj3555(639)
评论排行榜
1. 偶尔来点情感类的东西,心灵是需要养分的(0)
2. 对上篇文章的一点感触(0)
3. toj 最小生成树集萃(0)
4. 线段树(0)
5. 暑期集训——SCC(0)