P3834 【模板】可持久化线段树 1(主席树)
(静态区间第k大)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define clr(a) memset(a, 0, sizeof(a))
#define lowbit(x) x & -x
#define PB push_back
#define POP pop_back
const double pi = acos(-1);
const int maxn = 2e5 + 101;
const int maxm = (maxn << 5);
const ll mod = 998244353;
const int hash_mod = 19260817;
int n, m, k, cnt;
int ls[maxm], rs[maxm], sum[maxm], rt[maxm];
int a[maxn], b[maxn];
int build(int l, int r){
int root = ++ cnt;
if(l == r) return root;
int mid = (l + r) >> 1;
ls[root] = build(l, mid);
rs[root] = build(mid + 1, r);
return root;
}
int update(int k, int l, int r, int root){
int id = ++ cnt;
ls[id] = ls[root]; rs[id] = rs[root]; sum[id] = sum[root] + 1;
if(l == r) return id;
int mid = (l + r) >> 1;
if(k <= mid) ls[id] = update(k, l, mid, ls[id]);
if(k > mid) rs[id] = update(k, mid + 1, r, rs[id]);
return id;
}
int query(int k, int u, int v, int l, int r){
int mid = (l + r) >> 1;
int x = sum[ls[v]] - sum[ls[u]];
if(l == r) return l;
if(k <= x) return query(k, ls[u], ls[v], l, mid);
if(k > x) return query(k - x, rs[u], rs[v], mid + 1, r);
}
int main()
{
int l, r;
scanf("%d %d", &n, &m);
for(int i = 1 ; i <= n ; ++ i){
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b + 1, b + 1 + n);
int len = unique(b + 1, b + 1 + n) - b - 1;
rt[0] = build(1, len);
for(int i = 1 ; i <= n ; ++ i){
int x = lower_bound(b + 1, b + 1 + len, a[i]) - b;
rt[i] = update(x, 1, len, rt[i-1]);
}
for(int i = 1 ; i <= m ; ++ i){
scanf("%d %d %d", &l, &r, &k);
cout << b[query(k, rt[l-1], rt[r], 1, len)] <<endl;
}
return 0;
}
杭电多校第四场K-th Closest Distance
主席树查询小于k的数的个数 + 二分答案
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define clr(a) memset(a, 0, sizeof(a))
#define lowbit(x) x & -x
#define PB push_back
#define POP pop_back
const double pi = acos(-1);
const int maxn = 1e6 + 101;
const int maxm = (maxn << 5);
const ll mod = 998244353;
const int hash_mod = 19260817;
int n, m, k, cnt;
int ls[maxm], rs[maxm], sum[maxm], rt[maxm];
int a[maxn], b[maxn];
int build(int l, int r){
int root = ++ cnt;
if(l == r) return root;
int mid = (l + r) >> 1;
ls[root] = build(l, mid);
rs[root] = build(mid + 1, r);
return root;
}
int update(int k, int l, int r, int root){
int id = ++ cnt;
ls[id] = ls[root]; rs[id] = rs[root]; sum[id] = sum[root] + 1;
if(l == r) return id;
int mid = (l + r) >> 1;
if(k <= mid) ls[id] = update(k, l, mid, ls[id]);
if(k > mid) rs[id] = update(k, mid + 1, r, rs[id]);
return id;
}
int query(int k, int u, int v, int l, int r){
if(k >= b[r]) return sum[v] - sum[u];
if(k < b[l]) return 0;
int ans = 0;
int mid = (l + r) >> 1;
if(k <= b[mid]) ans += query(k, ls[u], ls[v], l, mid);
else{
ans += sum[ls[v]] - sum[ls[u]];
ans += query(k, rs[u], rs[v], mid + 1, r);
}
return ans;
}
int main()
{
int l, r, t, p;
scanf("%d", &t);
while(t--){
cnt = 0;
scanf("%d %d", &n, &m);
for(int i = 1 ; i <= n ; ++ i){
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b + 1, b + 1 + n);
int len = unique(b + 1, b + 1 + n) - b - 1;
rt[0] = build(1, len);
for(int i = 1 ; i <= n ; ++ i){
int x = lower_bound(b + 1, b + 1 + len, a[i]) - b;
rt[i] = update(x, 1, len, rt[i-1]);
}
int ans = 0;
for(int i = 1 ; i <= m ; ++ i){
scanf("%d %d %d %d", &l, &r, &p, &k);
l ^= ans; r ^= ans;
p ^= ans; k ^= ans;
int down = 0, up = INF;
ans = up;
while(down <= up){
int mid = (down + up) >> 1;
if(query(p+mid,rt[l-1],rt[r],1,len)-
query(p-mid-1,rt[l-1],rt[r],1,len) >= k) up = mid - 1, ans = min(ans, mid);
else down = mid + 1;
}
cout << ans << endl;
}
}
return 0;
}