题目
题目链接:http://poj.org/problem?id=2104
题目来源:《挑战》例题。
简要题意:求区间第 k 大。
题解
比较经典的题目,我用了三个方法来写。
其中第一种第三种我觉得比较好写,第二种出现了各种问题。
总的来说第一种速度快,但是代码长,第三种速度慢一些,但是代码比较短,第二种代码和第三种差不多,但是慢了很多,写起来很蛋疼。
第一种是我自己写的写法,后两种是书上的写法。好像还可以用其他乱七八糟树来弄。
题解1
首先可以离散化一下数据。
然后莫队去搞,然后用树状数组来维护整个个数,再去二分答案。
整个代码比较长,不过写起来还是比较方便的。
莫队+树状数组代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
// head
const int N = 1e5+5;
const int M = 5e3+5;
const int B = 1000;
struct BIT {
#define T int
T tree[N] ;
inline int lowbit(int x) {
return x&(-x);
}
void add(int x, T add, int n) {
for (int i = x; i <= n; i += lowbit(i)) {
tree[i] += add;
}
}
T sum(int x) {
T ans = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
ans += tree[i];
}
return ans;
}
T query(int k, int n) {
int l = 1, r = n, ans = n;
while (l <= r) {
int mid = (l + r) / 2;
if (sum(mid) >= k) {
ans = mid;
r = mid-1;
} else {
l = mid+