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; }