首页 > 代码库 > bzoj4923 K小值查询

bzoj4923 K小值查询

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4923

【题解】

发现每次操作,对于$(k, 2k]$的数,他们会变为$(0, k]$,而对于$(2k, +\infty)$的数,他们的相对次序不变,只是打了一个区间减tag而已。

那么每次暴力把$(k, 2k]$的数扔出来再插进去。发现每个数最多被插入$O(logn)$次,所以复杂度为$O(nlog^2n)$。

每次操作(包括询问)后都要splay下来保证树的形态 从而保证复杂度(迷

因为这个调了一早上。。

技术分享
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1e5 + 10;
const int mod = 1e9+7;

int n, Q, tt;
ll a[M];

struct Splay {
    int ch[M][2], fa[M], sz[M], siz, rt, tag[M];
//    int mx[M], mi[M];
    ll val[M];
    int re[M], rn;
    inline void set() {
        siz = 0, rn = 0;
    }
    
    inline int newnode() {
        int x = re[rn--];
        val[x] = 0; sz[x] = 1; tag[x] = 0;
        return x;
    }
    
    # define ls ch[x][0]
    # define rs ch[x][1]
    
    inline void up(int x) {
        if(!x) return ;
//        mx[x] = val[x]; mi[x] = val[x];
        sz[x] = sz[ls] + sz[rs] + 1;
//        if(ls) mx[x] = max(mx[ls], mx[x]), mi[x] = min(mi[ls], mi[x]);
//        if(rs) mx[x] = max(mx[rs], mx[x]), mi[x] = min(mi[rs], mi[x]);
    }
    
    inline void pushtag(int x, int tg) {
        if(!x) return;
        tag[x] += tg;
        val[x] -= tg;
//        mx[x] -= tg;
//        mi[x] -= tg;
    }
    
    inline void down(int x) {
        if(!x || !tag[x]) return ;
        pushtag(ls, tag[x]);
        pushtag(rs, tag[x]);
        tag[x] = 0;
    }
    
    # undef ls
    # undef rs
    
    inline void rotate(int x, int &rt) {
        int y = fa[x], z = fa[y], ls = ch[y][1] == x, rs = ls^1;
        if(rt == y) rt = x;
        else ch[z][ch[z][1] == y] = x;
        fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z;
        ch[y][ls] = ch[x][rs]; ch[x][rs] = y;
        up(y), up(x);
    }
    
    int st[M];
    inline void splay(int x, int &rt) {
        int tx = x, stn = 0;
        while(tx != rt) st[++stn] = tx, tx = fa[tx];
        st[++stn] = tx;
        for (int i=stn; i; --i) down(st[i]);
        while(x != rt) {
            int y = fa[x], z = fa[y];
            if(y != rt) {
                if((ch[z][0] == y) ^ (ch[y][0] == x)) rotate(x, rt);
                else rotate(y, rt);
            }
            rotate(x, rt);
        }
    }
    
    inline int find(int x, int rk) {
        down(x);
        if(sz[ch[x][0]] + 1 == rk) return x;
        if(sz[ch[x][0]] + 1 < rk) return find(ch[x][1], rk - sz[ch[x][0]] - 1);
        else return find(ch[x][0], rk);
    }

    inline void build(int l, int r, int f) {
        if(l > r) return ;
        int mid = l+r>>1, x = mid, lst = f;
        if(l == r) sz[x] = 1;
        else build(l, mid-1, mid), build(mid+1, r, mid);
        val[x] = a[mid]; fa[x] = lst; ch[lst][mid >= f] = x;
        up(x);
    }
    
    inline int QUERY(int k) {
        int x = find(rt, k+1); splay(x, rt); 
        return val[x];
    }
    
    inline int findbef(int x, int v) {
        if(!x) return 0;
        int t; down(x);
        if(val[x] <= v) {
            t = findbef(ch[x][1], v);
            if(!t) return x; else return t;
        } else return findbef(ch[x][0], v);
    }
    
    inline int findaft(int x, int v) {
        if(!x) return 0;
        int t; down(x);
        if(val[x] > v) {
            t = findaft(ch[x][0], v);
            if(!t) return x; else return t;
        } else return findaft(ch[x][1], v);
    }
    
    inline void del(int x) {
        if(!x) return ;
        down(x);
        del(ch[x][0]);
        re[++rn] = x;
        a[++n] = val[x];
        del(ch[x][1]);
        ch[x][0] = ch[x][1] = fa[x] = 0;
    }
    
    int ro;
    inline void ins(int &x, int v, int lst) {
        if(!x) {
            ro = x = newnode();
            fa[x] = lst; val[x] = v;
            return ;
        }
        down(x);
        ins(ch[x][v >= val[x]], v, x);
        up(x);
    }
    
    inline void OPTION(int k) {
        int x = findbef(rt, k), y = findaft(rt, k*2);
        splay(x, rt); splay(y, ch[x][1]); int z = ch[y][0];
        n = 0; del(ch[y][0]); ch[y][0] = 0;
        up(y), up(x); pushtag(y, k);
        for (int i=1; i<=n; ++i) { ins(rt, a[i]-k, 0); splay(ro, rt); }
    }
    
    inline void debug(int x) {
        if(!x) return ;
        debug(ch[x][0]);
        printf("x = %d, ls = %d, rs = %d, fa = %d, val = %d, tag = %d\n", x, ch[x][0], ch[x][1], fa[x], val[x], tag[x]);
        debug(ch[x][1]);
    }
}T;

int main() {
    cin >> n >> Q; T.set();
    a[1] = -1e18;
    for (int i=2; i<=n+1; ++i) scanf("%lld", a+i);
    a[tt = n+2] = 1e18;
    sort(a+2, a+n+2);
    T.build(1, n+2, 0);
    T.rt = n+3 >> 1; T.siz = n+2;
    int opt, k;
    while(Q--) {
        scanf("%d%d", &opt, &k);
        if(opt == 1) printf("%d\n", T.QUERY(k));
        else T.OPTION(k);
    }
    return 0;
}
View Code

 

bzoj4923 K小值查询