= Vain学习(C/C++ acm算法 python Linux Golang)的个人网站 =

HDU 3282 动态开点+区间第k小

Posted on

题意:

给n个数,把这n个数以此插入容器中,当插入的数量是奇数个时输出中位数

样例:

Sample Input
3
1 9
1 2 3 4 5 6 7 8 9
2 9
9 8 7 6 5 4 3 2 1
3 23
23 41 13 22 -3 24 -31 -11 -8 -7
3 5 103 211 -311 -45 -67 -73 -81 -99
-33 24 56

Sample Output
1 5
1 2 3 4 5
2 5
9 8 7 6 5
3 12
23 23 22 22 13 3 5 5 3 -3
-7 -3

吐槽:

今天有点事,没看来得及看这道题,其实就是询问整体区间第k小的板题


思路:

我没怎么看数据范围,直接用动态开点线段树写了,当然这题数据范围很小,
普通线段树也可以写,因为数据范围并不是很大,如果数据范围给到1e9,那也只能动态开点或者
离散化写了,这题主要考察权值线段树,我们可以统计权值,我们询问的值如果小于等于左儿子节点的权值,呢么
我们询问的值一定在左边,我们向左递归,反之减去左边权值向右递归

参考代码:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
using namespace std;
const int inf = 1 << 30;
const int maxn = 1e6 + 5;
typedef long long ll;
const int N = 1005;
typedef unsigned long long ull;
//char s[maxn], str[maxn], s3[maxn];
//char s[N][N];
//ll da[maxn], dab[maxn], daba[maxn], sum[maxn];
int a[maxn];
struct node
{
int ls, rs, sum;
} tr[maxn << 1];
int cnt;
void inser(int &k, int L, int R, int pos)
{
if (!k)
k = ++cnt;
tr[k].sum++;
if (L == R)
{
return;
}
int mid = L + R >> 1;
if (mid >= pos)
inser(tr[k].ls, L, mid, pos);
else
inser(tr[k].rs, mid + 1, R, pos);
}
int ask(int k, int L, int R, int ik)
{
if (L == R)
{
return L;
}
int mid = L + R >> 1;
int sum = tr[tr[k].ls].sum;
if (sum >= ik)
return ask(tr[k].ls, L, mid, ik);
else
return ask(tr[k].rs, mid + 1, R, ik - sum);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, m, k;
int t;
cin >> t;
while (t--)
{
memset(a, 0, sizeof a);
memset(tr, 0, sizeof(tr));
cin >> m >> n;
k = cnt = 0;
int x, id = 0;
for (int i = 1; i <= n; i++)
{
cin >> x;
inser(k, -inf, inf, x);
if (i & 1)
{
int pos = (1 + i) / 2;
a[id++] = ask(k, -inf, inf, pos);
}
}
cout << m << ' ' << (n + 1) / 2 ;
for (int i = 0; i <id; i++)
{
if (i % 10 == 0)
cout << endl;
if (i % 10 == 0)
cout << a[i];
else
cout << ' ' << a[i];
}
cout<<endl;
}
}