主席树/权值线段树(小于k的数的个数 和 静态区间第k大)

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 ls rt << 1, l, mid
//#define rs rt << 1 | 1, mid + 1, r
#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;
}
//123000321013200987000789

杭电多校第四场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 ls rt << 1, l, mid
//#define rs rt << 1 | 1, mid + 1, r
#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;
}
//123000321013200987000789

你可能感兴趣的:(主席树/权值线段树(小于k的数的个数 和 静态区间第k大))