POJ2104、POJ2761:
题意:区间第K小。
两道题几乎是一样的。
AC代码:
/*---------------------------------
File name: poj2104.cpp
Author: Snpilola
Creation date: 2019-08-09 14:17
---------------------------------*/
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define LL long long
#define mkp make_pair
#define PLL pair<LL, LL>
#define PII pair<int, int>
#define Pque priority_queue
using namespace std;
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int ls[maxn << 5], rs[maxn << 5], cnt[maxn << 5], root[maxn << 5], tot;
int num[maxn], hash[maxn];
void build(int l, int r, int &rt){
rt = tot++;
cnt[rt] = 0;
if(l == r) return;
int mid = (l + r) >> 1;
build(l, mid, ls[rt]);
build(mid + 1, r, rs[rt]);
}
void update(int last, int p, int l, int r, int &rt){
rt = tot++;
ls[rt] = ls[last], rs[rt] = rs[last];
cnt[rt] = cnt[last] + 1;
if(l == r) return;
int mid = (l + r) >> 1;
if(p <= mid) update(ls[last], p, l, mid, ls[rt]);
else update(rs[last], p, mid + 1, r, rs[rt]);
}
int query(int ss, int tt, int l, int r, int k){
if(l == r) return l;
int mid = (l + r) >> 1, sum = cnt[ls[tt]] - cnt[ls[ss]];
if(k <= sum) return query(ls[ss], ls[tt], l, mid, k);
else return query(rs[ss], rs[tt], mid + 1, r, k - sum);
}
int main(){
int n, m, l, r, k;
while(~ scanf("%d %d", &n, &m)){
for(int i = 1; i <= n; ++i){
scanf(" %d", &num[i]);
hash[i] = num[i];
}
sort(hash + 1, hash + 1 + n);
int size = unique(hash + 1, hash + 1 + n) - hash - 1;//unique前先sort
//unique函数返回最后一个不重复元素,实际数组长度无变化
for(int i = 1; i <= n; ++i){
num[i] = lower_bound(hash + 1, hash + size + 1, num[i]) - hash;
}
tot = 0;
build(1, size, root[0]);//建空树
for(int i = 0; i < 4 * size; i++) printf("%d %d %d\n", root[i], ls[i], rs[i]);
//printf("----------\n");
for(int i = 1; i <= n; ++i){
update(root[i - 1], num[i], 1, size, root[i]);//填树
//printf("%d %d %d\n", root[i], ls[root[i]], rs[root[i]]);
}
while(m--){
scanf("%d %d %d", &l, &r, &k);//区间[l, r]的第k小||大
printf("%d\n", hash[query(root[l - 1], root[r], 1, size, k)]);
}
}
return 0;
}
/*---------------------------------
File name: poj2761.cpp
Author: Snpilola
Creation date: 2019-08-08 10:32
---------------------------------*/
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define LL long long
#define mkp make_pair
#define PLL pair<LL, LL>
#define PII pair<int, int>
#define Pque priority_queue
using namespace std;
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int a[maxn];
int Hash[maxn];
int root[maxn << 5], ls[maxn << 5], rs[maxn << 5], cnt[maxn << 5];
int tot;
void build(int l, int r, int &rt){
rt = tot++;
cnt[rt] = 0;
if(l == r) return;
int mid = (l + r) >> 1;
build(l, mid, ls[rt]);
build(mid + 1, r, rs[rt]);
}
void update(int last, int p, int l, int r, int &rt){
rt = tot++;
ls[rt] = ls[last];
rs[rt] = rs[last];
cnt[rt] = cnt[last] + 1;
if(l == r) return ;
int mid = (l + r) >> 1;
if(p <= mid) update(ls[rt], p, l, mid, ls[rt]);
else update(rs[rt], p, mid + 1, r, rs[rt]);
}
int query(int ss, int tt, int l, int r, int k){
if(l == r) return r;
int mid = (l + r) >> 1;
int sum = cnt[ls[tt]] - cnt[ls[ss]];
if(k <= sum) query(ls[ss], ls[tt], l, mid, k);
else query(rs[ss], rs[tt], mid + 1, r, k - sum);
}
int main(){
int t; scanf("%d", &t);
while(t--){
int n, m; scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i){
scanf(" %d", &a[i]);
Hash[i] = a[i];
}
sort(Hash + 1, Hash + 1 + n);
int Size = unique(Hash + 1, Hash + 1 + n) - Hash - 1;
for(int i = 1; i <= n; i++){
a[i] = lower_bound(Hash + 1, Hash + 1 + Size, a[i]) - Hash;
}
tot = 0;
build(1, Size, root[0]);
for(int i = 1; i <= n; i++){
update(root[i - 1], a[i], 1, Size, root[i]);
}
while(m--){
int i, j, k;
scanf("%d %d %d", &i, &j, &k);
printf("%d\n", Hash[query(root[i - 1], root[j], 1, Size, k)]);
}
}
return 0;
}
HDU4417:
Input:
1
10 10
0 5 2 7 5 4 3 8 7 7
2 8 6
3 5 0
1 3 1
1 9 4
0 1 0
3 5 5
5 5 1
4 6 3
1 5 7
5 7 3
Output:
Case 1:
4
0
0
3
1
2
0
1
5
1
题意:求给定区间【L, R】中不大于H的数的个数。
思路:只需要改一下query的部分就可以了。
AC代码:
/*---------------------------------
File name: hdu4417.cpp
Author: Snpilola
Creation date: 2019-08-08 11:07
---------------------------------*/
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define LL long long
#define mkp make_pair
#define PLL pair<LL, LL>
#define PII pair<int, int>
#define Pque priority_queue
using namespace std;
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int a[maxn];
int Hash[maxn];
int root[maxn << 5], ls[maxn << 5], rs[maxn << 5], cnt[maxn << 5];
int tot;
void build(int l, int r, int &rt){
rt = tot++;
cnt[rt] = 0;
if(l == r) return;
int mid = (l + r) >> 1;
build(l, mid, ls[rt]);
build(mid + 1, r, rs[rt]);
}
void update(int last, int p, int l, int r, int &rt){
rt = tot++;
ls[rt] = ls[last];
rs[rt] = rs[last];
cnt[rt] = cnt[last] + 1;
if(l == r){
//printf("cnt = %d, l = %d, r = %d\n", cnt[rt], l, r);
return ;
}
int mid = (l + r) >> 1;
if(p <= mid) update(ls[last], p, l, mid, ls[rt]);
else update(rs[last], p, mid + 1, r, rs[rt]);
}
int query(int ss, int tt, int l, int r,int x){
if(l == r) return x < l ? 0 : (cnt[tt] - cnt[ss]);
int mid = (l + r) >> 1;
if(x <= mid) return query(ls[ss], ls[tt], l, mid, x);
else return cnt[ls[tt]] - cnt[ls[ss]] + query(rs[ss], rs[tt], mid + 1, r, x);
}
int main(){
int t; scanf("%d", &t);
int cast = 0;
while(t--){
int n, m; scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++){
scanf(" %d", &a[i]);
Hash[i] = a[i];
}
sort(Hash + 1, Hash + 1 + n);
int Size = unique(Hash + 1, Hash + 1 + n) - Hash - 1;
for(int i = 1; i <= n; i++){
a[i] = lower_bound(Hash + 1, Hash + 1 + Size, a[i]) - Hash;
}
//for(int i = 1; i <= n; i++) printf("%d ", a[i]); cout << endl;
tot = 0;
build(1, Size, root[0]);
for(int i = 1; i <= n; i++){
update(root[i - 1], a[i], 1, Size, root[i]);
}
printf("Case %d:\n", ++cast);
while(m--){
int i, j, k;
scanf("%d %d %d", &i, &j, &k);
k = upper_bound(Hash + 1, Hash + 1 + Size, k) - Hash - 1;
printf("%d\n", query(root[i], root[j + 1], 1, Size, k));
}
}
return 0;
}