1、题目大意:区间第k大,单点修改
2、随便搞搞就好了= =,树套树或主席树,我写的很丑
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; struct Node{ Node *ch[2]; int cnt, num, r, v; bool operator < (const Node& rhs) const{ return r < rhs.r; } int cmp(int x){ if(x == v) return -1; if(x < v) return 0; return 1; } void maintain(){ cnt = num; if(ch[0]) cnt += ch[0] -> cnt; if(ch[1]) cnt += ch[1] -> cnt; } } *root[400100], ft[6000000]; int tot; int a[400100]; void treap_rotate(Node* &o, int d){ Node* k = o -> ch[d ^ 1]; o -> ch[d ^ 1] = k -> ch[d]; k -> ch[d] = o; o -> maintain(); k -> maintain(); o = k; return; } void treap_insert(Node* &o, int x){ if(o == NULL){ o = &ft[tot ++]; o -> ch[0] = o -> ch[1] = NULL; o -> cnt = o -> num = 1; o -> v = x; o -> r = rand(); } else{ int d = o -> cmp(x); if(d == -1){ o -> num ++; } else{ treap_insert(o -> ch[d], x); if(o < o -> ch[d]) treap_rotate(o, d ^ 1); } } o -> maintain(); } void treap_remove(Node* &o, int x){ int d = o -> cmp(x); if(d == -1){ if(o -> num > 1) o -> num --; else if(o -> ch[0] == NULL) o = o -> ch[1]; else if(o -> ch[1] == NULL) o = o -> ch[0]; else { int d2; if(o -> ch[0] > o -> ch[1]) d2 = 1; else d2 = 0; treap_rotate(o, d2); treap_remove(o -> ch[d2], x); } } else treap_remove(o -> ch[d], x); if(o) o -> maintain(); } int treap_lessk(Node* &o, int k){ if(o == NULL) return 0; int d = o -> cmp(k); if(d == -1){ int ret = o -> num; if(o -> ch[0]) ret += o -> ch[0] -> cnt; return ret; } else if(d == 0){ return treap_lessk(o -> ch[0], k); } else{ int ss = o -> num; if(o -> ch[0]) ss += o -> ch[0] -> cnt; return treap_lessk(o -> ch[1], k) + ss; } } void add(int l, int r, int o, int x, int value, int nm){ if(nm == 2) treap_remove(root[o], a[x]); treap_insert(root[o], value); if(l == r){ a[x] = value; return; } int mid = (l + r) / 2; if(x <= mid) add(l, mid, 2 * o, x, value, nm); else add(mid + 1, r, 2 * o + 1, x, value, nm); } int query(int l, int r, int o, int x, int y, int k){ if(x <= l && r <= y){ return treap_lessk(root[o], k); } int ret = 0; int mid = (l + r) / 2; if(x <= mid) ret += query(l, mid, 2 * o, x, y, k); if(y > mid) ret += query(mid + 1, r, 2 * o + 1, x, y, k); return ret; } void init(){ for(int i = 0; i <= 400000; i ++) root[i] = NULL; memset(a, 0, sizeof(a)); tot = 0; } int main(){ int n, m; while(scanf("%d", &n) != EOF){ tot = 0; init(); for(int i = 1; i <= n; i ++){ int x; scanf("%d", &x); add(1, n, 1, i, x, 1); } int m; scanf("%d", &m); for(int i = 1; i <= m; i ++){ int op, x, y, z; scanf("%d", &op); if(op == 1){ scanf("%d%d", &x, &y); add(1, n, 1, x, y, 2); } else{ scanf("%d%d%d", &x, &y, &z); int L = 0, R = 1000000000; while(L < R){ int mid = (L + R) / 2; if(query(1, n, 1, x, y, mid) < z) L = mid + 1; else R = mid; } printf("%d\n", L); } } } return 0; }