Visit Counter
AmazingCounters.com

1、题目大意:区间第k大,单点修改。。。但是卡空间。。。
2、分析:因为卡空间。。。所以不可以用nlog^2n的东西,后来po神一语道破天机。。。用线段树套treap
好久不写线段树套treap了,所以脑补了一个点。。。
然后如果用树套树的话,那么这题就是模板题了。。。
记住要二分答案哦
由于我是静态内存,所以快,所以没有被卡。。
3、代码:

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