• 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
    ", 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
    ", T.QUERY(k));
            else T.OPTION(k);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    python学习(二十三) String(下) 分片和索引
    python学习(二十二) String(上)
    微服务网关
    【转】linux 软连接 硬链接
    设计模式--观察者模式
    设计模式--策略模式
    ubuntu-server 安装redis
    【转】linux的hostname修改详解
    【转】ftp的两种模式
    【转】linux下find查找命令用法
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj4923.html
Copyright © 2020-2023  润新知