11114: 【原1114】Problem A
题目
题目描述
author: Zheyi Pan 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1114
Description
给定n个数a[1], a[2], ..., a[n],m个询问(l, r, k),询问a[l], a[l+1], ..., a[r]中第k小的数是多少。保证0<=k<=r–l+1。
Input Format
第一行一个正整数n。
第二行n个数,表示a[i]。
接下来一个正整数m。
以下m行每行三个整数l, r, k。
Output Format
输出共m行,每行一个数表示a[l], a[l+1], ..., a[r]中的第k小数。
Sample Input
5
1 2 3 4 5
3
1 3 2
1 4 1
2 5 4
Sample Output
2
1
5
Restrictions
60%: n, m <= 1000。
80%: 数据满足询问区间互相不包含。
100%:n, m <= 300000,|a[i]| <= 10^9。
内存限制:512MB
时间限制:2000ms
FineArtz's solution
/* Problem A */
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 300005;
class Node{
public:
int sum = 0, l = 0, r = 0;
};
int a[MAXN], s[MAXN], root[MAXN] = {0};
int cnt = 0;
Node tree[MAXN << 5];
int createNode(int sum, int l, int r){
tree[++cnt].sum = sum;
tree[cnt].l = l;
tree[cnt].r = r;
return cnt;
}
void insert(int &root, int preroot, int pos, int l, int r){
root = createNode(tree[preroot].sum + 1, tree[preroot].l, tree[preroot].r);
if (l == r)
return;
int mid = (l + r) / 2;
if (pos <= mid)
insert(tree[root].l, tree[preroot].l, pos, l, mid);
else
insert(tree[root].r, tree[preroot].r, pos, mid + 1, r);
}
int query(int left, int right, int k, int l, int r){
if (l == r)
return l;
int mid = (l + r) / 2;
int sum = tree[tree[right].l].sum - tree[tree[left].l].sum;
if (k <= sum)
return query(tree[left].l, tree[right].l, k, l, mid);
else
return query(tree[left].r, tree[right].r, k - sum, mid + 1, r);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n;
for (int i = 1; i <= n; ++i){
cin >> a[i];
s[i] = a[i];
}
sort(s + 1, s + n + 1);
int num = unique(s + 1, s + n + 1) - (s + 1);
for (int i = 1; i <= n; ++i){
int pos = lower_bound(s + 1, s + num + 1, a[i]) - s;
insert(root[i], root[i - 1], pos, 1, num);
}
cin >> m;
while (m--){
int x, y, k;
cin >> x >> y >> k;
int t = query(root[x - 1], root[y], k, 1, num);
cout << s[t] << '\n';
}
return 0;
}
yyong119's solution
#include <cstdio>
#include <algorithm>
#define MAX 300010
using namespace std;
const int INF = 0xFFFFFFF;
int nums[MAX], sorted[MAX], root[MAX];
int cnt;
struct TMD {
int sum, L_son, R_son;
} Tree[MAX << 5];
inline int CreateNode(int _sum, int _L_son, int _R_son) {
int idx = ++cnt;
Tree[idx].sum = _sum;
Tree[idx].L_son = _L_son;
Tree[idx].R_son = _R_son;
return idx;
}
void Insert(int & root, int pre_rt, int pos, int L, int R) {
root = CreateNode(Tree[pre_rt].sum + 1, Tree[pre_rt].L_son, Tree[pre_rt].R_son);
if (L == R) return;
int M = (L + R) >> 1;
if (pos <= M)
Insert(Tree[root].L_son, Tree[pre_rt].L_son, pos, L, M);
else
Insert(Tree[root].R_son, Tree[pre_rt].R_son, pos, M + 1, R);
}
int Query(int S, int E, int L, int R, int K) {
if (L == R) return L;
int M = (L + R) >> 1;
int sum = Tree[Tree[E].L_son].sum - Tree[Tree[S].L_son].sum;
if (K <= sum)
return Query(Tree[S].L_son, Tree[E].L_son, L, M, K);
else
return Query(Tree[S].R_son, Tree[E].R_son, M + 1, R, K - sum);
}
int main() {
int n, m, num, pos, T;
scanf("%d", &n);
cnt = 0; root[0] = 0;
for (int i = 1; i <= n; ++i) {
scanf("%d", &nums[i]);
sorted[i] = nums[i];
}
sort(sorted + 1, sorted + 1 + n);
num = unique(sorted + 1, sorted + n + 1) - (sorted + 1);
for (int i = 1; i <= n; ++i) {
pos = lower_bound(sorted + 1, sorted + num + 1, nums[i]) - sorted;
Insert(root[i], root[i - 1], pos, 1, num);
}
scanf("%d", &m);
int l, r, k;
while (m--) {
scanf("%d %d %d", &l, &r, &k);
pos = Query(root[l - 1], root[r], 1, num, k);
printf("%d\n", sorted[pos]);
}
return 0;
}