平衡树三道题终于全A了。为什么说分块是伪呢,毕竟这是平衡树的题目,然后我用了分块(我弱啊,不会树套)。听说TY上还有大爷直接用sort A掉了,这算什么嘛,还有话说我BZOJ上A掉的代码在TY上死活RE30分,还WA了两个点。不管了。。

分块的话没什么好说的,就一个带修改的区间第K大,直接上代码

//tyvj 1730.cpp
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>

//#define LOCAL
#define READ_FREAD
//#define READ_FILE
//#define VISUAL_STUDIO

const int MAXS = 5 * 1024 * 1024;
const int MAXN = 100000;
const int MAX_LENGTH_BLOCK = 500;

#ifdef LOCAL
#define LOCAL_TIME
#define LOCAL_DEBUG
//#define LOCAL_DEBUG_NOUT
//#define LOCAL_SIMP
#endif

#ifdef LOCAL_TIME
#include<ctime>
#endif

#ifdef VISUAL_STUDIO
#pragma warning(disable:4996)
#endif

#ifdef READ_FREAD
//char fread_string[MAXS];
//char *fread_point = fread_string;
char fread_point;

inline int get_int()
{
    int ret = 0;
    bool sign = false;
    while ((fread_point < '0') || (fread_point > '9') || (fread_point == '-'))
    {
        if (fread_point == '-')
        {
            sign = true;
        }
        else
        {
            sign = false;
        }
        fread_point = getchar();
    }
    while ((fread_point >= '0') && (fread_point <= '9'))
    {
        ret = ret * 10 + fread_point - '0';
        fread_point = getchar();
    }
    if (sign)
    {
        return -ret;
    }
    return ret;
}
#endif

inline void read(int &a)
{
#ifdef READ_FREAD
    a = get_int();
#else
    scanf("%d", &a);
#endif
}

typedef long long ll;

struct block_node
{
    int val[MAX_LENGTH_BLOCK];
    int order[MAX_LENGTH_BLOCK];
    int size;
};

inline int min(const int a, const int b)
{
    if (a == -1)
    {
        return b;
    }
    if (b == -1)
    {
        return a;
    }
    return a < b ? a : b;
}

block_node block_list[MAXN / MAX_LENGTH_BLOCK];

const int OP_Q_RANK = 1;
const int OP_Q_NUM = 2;
const int OP_CHANGE = 3;
const int OP_PREV = 4;
const int OP_NEXT = 5;

int n, m;
int init_read[MAXN];
int op, op_l, op_r, k;
int num_max = -1, num_min = -1;

inline void block_init(const int n)
{
    for (int i = 0, j = 0; j < n; i++, j += MAX_LENGTH_BLOCK)
    {
        for (int t = j; t < j + MAX_LENGTH_BLOCK, t < n; t++)
        {
            block_list[i].val[t - j] = init_read[t];
        }
        block_list[i].size = std::min(MAX_LENGTH_BLOCK, n - j);
        memcpy(block_list[i].order, block_list[i].val, block_list[i].size * sizeof(int));
        std::sort(block_list[i].order, block_list[i].order + block_list[i].size);
    }
}

inline int block_find(int &x)
{
    int ret = x / MAX_LENGTH_BLOCK;
    x %= MAX_LENGTH_BLOCK;
    return ret;
}

inline int block_smaller(const int block, const int val)
{
    int l = 0, r = block_list[block].size;
    int mid;
    while (l + 1 < r)
    {
        mid = (l + r) >> 1;
        if (block_list[block].order[mid] >= val)
        {
            r = mid;
        }
        else
        {
            l = mid + 1;
        }
    }
    while ((l < block_list[block].size) && (block_list[block].order[l] < val))
    {
        l++;
    }
    return l;
}

inline int block_query_smaller(const int block, const int l, const int r, const int val)
{
    int ret = 0;
    for (int i = l; i <= r; i++)
    {
        if (block_list[block].val[i] < val)
        {
            ret++;
        }
    }
    return ret;
}

inline int block_b_smaller(const int block, const int val)
{
    int binary_l = 0, binary_r = block_list[block].size, mid;
    while (binary_l + 1 < binary_r)
    {
        mid = (binary_l + binary_r) >> 1;
        if (block_list[block].order[mid] >= val)
        {
            binary_r = mid;
        }
        else
        {
            binary_l = mid;
        }
    }
    /*while ((binary_l < block_list[block].size - 1) && (block_list[block].order[binary_l + 1] < val))
    {
        binary_l++;
    }*/
    while ((binary_l > 0) && (block_list[block].order[binary_l] >= val))
    {
        binary_l--;
    }
    if (block_list[block].order[binary_l] >= val)
    {
        return -1;
    }
    return block_list[block].order[binary_l];
}

inline int block_query_b_smaller(const int block, const int l, const int r, const int val)
{
    int max_num = -1;
    for (int i = l; i <= r; i++)
    {
        if (block_list[block].val[i] < val)
        {
            max_num = std::max(max_num, block_list[block].val[i]);
        }
    }
    return max_num;
}

inline int block_s_bigger(const int block, const int val)
{
    int binary_l = 0, binary_r = block_list[block].size, mid;
    while (binary_l + 1 < binary_r)
    {
        mid = (binary_l + binary_r) >> 1;
        if (block_list[block].order[mid] > val)
        {
            binary_r = mid;
        }
        else
        {
            binary_l = mid;
        }
    }
    while ((binary_l < block_list[block].size - 1) && (block_list[block].order[binary_l] <= val))
    {
        binary_l++;
    }
    if (block_list[block].order[binary_l] <= val)
    {
        return -1;
    }
    return block_list[block].order[binary_l];
}

inline int block_query_s_bigger(const int block, const int l, const int r, const int val)
{
    int min_num = -1;
    for (int i = l; i <= r; i++)
    {
        if (block_list[block].val[i] > val)
        {
            min_num = min(min_num, block_list[block].val[i]);
        }
    }
    return min_num;
}

inline int block_query_rank(int l, int r, const int val)
{
    int block_l = block_find(l);
    int block_r = block_find(r);
    if (block_l == block_r)
    {
        if ((l == 0) && (r == block_list[block_l].size - 1))
        {
            return block_smaller(block_l, val) + 1;
        }
        else
        {
            return block_query_smaller(block_l, l, r, val) + 1;
        }
    }
    else
    {
        int ret = 0;
        if (l == 0)
        {
            ret += block_smaller(block_l, val);
        }
        else
        {
            ret += block_query_smaller(block_l, l, block_list[block_l].size - 1, val);
        }
        if (r == block_list[block_l].size - 1)
        {
            ret += block_smaller(block_r, val);
        }
        else
        {
            ret += block_query_smaller(block_r, 0, r, val);
        }
        for (int i = block_l + 1; i < block_r; i++)
        {
            ret += block_smaller(i, val);
        }
        return ret + 1;
    }
}

inline int block_query_num(const int l, const int r, const int k)
{
    int binary_l = num_min, binary_r = num_max, mid;
    int ret;
    while (binary_l < binary_r)
    {
        mid = (binary_l + binary_r) >> 1;
        ret = block_query_rank(l, r, mid) - 1;
        if ((ret < k) && (block_query_rank(l, r, mid + 1) > k))
        {
            return mid;
        }
        else if (ret < k)
        {
            binary_l = mid + 1;
        }
        else
        {
            binary_r = mid - 1;
        }
    }
    return binary_l;
}

inline void block_change(int pt, const int val)
{
    int block_pt = block_find(pt);
    if (block_list[block_pt].val[pt] == val)
    {
        return;
    }
    int binary_l = 0, binary_r = block_list[block_pt].size, mid;
    int loop = -1;
    /*while (binary_l + 1 < binary_r)
    {
        mid = (binary_l + binary_r) >> 1;
        if (block_list[block_pt].order[mid] == block_list[block_pt].val[pt])
        {
            loop = mid;
            break;
        }
        else if (block_list[block_pt].order[mid] > block_list[block_pt].val[pt])
        {
            binary_l = mid;
        }
        else
        {
            binary_r = mid;
        }
    }*/
    for (int i = 0; i < block_list[block_pt].size; i++)
    {
        if (block_list[block_pt].order[i] == block_list[block_pt].val[pt])
        {
            loop = i;
        }
    }
    if (loop == -1)
    {
        loop = binary_l;
    }
    if (block_list[block_pt].val[pt] < val)
    {
        while ((loop + 1 < block_list[block_pt].size) && (block_list[block_pt].order[loop + 1] < val))
        {
            block_list[block_pt].order[loop] = block_list[block_pt].order[loop + 1];
            loop++;
        }
        block_list[block_pt].order[loop] = val;
    }
    else
    {
        while ((loop > 0) && (block_list[block_pt].order[loop - 1] > val))
        {
            block_list[block_pt].order[loop] = block_list[block_pt].order[loop - 1];
            loop--;
        }
        block_list[block_pt].order[loop] = val;
    }
    block_list[block_pt].val[pt] = val;
}

inline int block_prev(int l, int r, const int val)
{
    int block_l = block_find(l);
    int block_r = block_find(r);
    if (block_l == block_r)
    {
        if ((l == 0) && (r == block_list[block_l].size - 1))
        {
            return block_b_smaller(block_l, val);
        }
        else
        {
            return block_query_b_smaller(block_l, l, r, val);
        }
    }
    else
    {
        int ret;
        if (l == 0)
        {
            ret = block_b_smaller(block_l, val);
        }
        else
        {
            ret = block_query_b_smaller(block_l, l, block_list[block_l].size - 1, val);
        }
        if (r == block_list[block_r].size - 1)
        {
            ret = std::max(ret, block_b_smaller(block_r, val));
        }
        else
        {
            ret = std::max(ret, block_query_b_smaller(block_r, 0, r, val));
        }
        for (int i = block_l + 1; i < block_r; i++)
        {
            ret = std::max(ret, block_b_smaller(i, val));
            //ret = std::max(ret, block_query_b_smaller(i, 0, block_list[block_l].size - 1, val));
        }
        return ret;
    }
}

inline int block_next(int l, int r, const int val)
{
    int block_l = block_find(l);
    int block_r = block_find(r);
    if (block_l == block_r)
    {
        if ((l == 0) && (r == block_list[block_l].size - 1))
        {
            return block_s_bigger(block_l, val);
        }
        else
        {
            return block_query_s_bigger(block_l, l, r, val);
        }
    }
    else
    {
        int ret;
        if (l == 0)
        {
            ret = block_s_bigger(block_l, val);
        }
        else
        {
            ret = block_query_s_bigger(block_l, l, block_list[block_l].size - 1, val);
        }
        if (r == block_list[block_r].size - 1)
        {
            ret = min(ret, block_s_bigger(block_r, val));
        }
        else
        {
            ret = min(ret, block_query_s_bigger(block_r, 0, r, val));
        }
        for (int i = block_l + 1; i < block_r; i++)
        {
            ret = min(ret, block_s_bigger(i, val));
        }
        return ret;
    }
}

#ifdef LOCAL_DEBUG
inline void checker()
{
    int loop = 0;
    int pt = 0;
    for (int i = 0; i < n; i++)
    {
        if (pt >= block_list[loop].size)
        {
            pt = 0;
            loop++;
        }
        printf("%d ", block_list[loop].val[pt]);
        pt++;
    }
    printf("n");
}
#endif

#ifndef LOCAL_SIMP
int main()
{
#ifdef LOCAL_TIME
    ll start_time_ = clock();
#endif
#ifdef READ_FILE
    freopen("input4.in", "r", stdin);
    freopen("3196.out", "w", stdout);
#endif
    fread_point = getchar();
    read(n);
    read(m);
    for (int i = 0; i < n; i++)
    {
        read(init_read[i]);
        num_max = std::max(num_max, init_read[i]);
        num_min = min(num_min, init_read[i]);
    }
    block_init(n);
    for (int i = 0; i < m; i++)
    {
        read(op);
#ifdef LOCAL_DEBUG
        printf("%d %d ", i, op);
        if (i == 446)
        {
            //printf("DEBUG ");
        }
#endif
        if (op == OP_Q_RANK)
        {
            read(op_l);
            read(op_r);
            read(k);
#ifdef LOCAL_DEBUG
            printf("%d %d %dn", op_l, op_r, k);
#endif
#ifndef LOCAL_DEBUG_NOUT
            printf("%dn", block_query_rank(op_l - 1, op_r - 1, k));
#endif
        }
        else if (op == OP_Q_NUM)
        {
            read(op_l);
            read(op_r);
            read(k);
#ifdef LOCAL_DEBUG
            printf("%d %d %dn", op_l, op_r, k);
#endif
#ifndef LOCAL_DEBUG_NOUT
            printf("%dn", block_query_num(op_l - 1, op_r - 1, k));
#endif
        }
        else if (op == OP_CHANGE)
        {
            read(op_l);
            read(k);
            num_max = std::max(num_max, k);
            num_min = min(num_min, k);
#ifdef LOCAL_DEBUG
            printf("%d %dn", op_l, k);
#endif
            block_change(op_l - 1, k);
        }
        else if (op == OP_PREV)
        {
            read(op_l);
            read(op_r);
            read(k);
#ifdef LOCAL_DEBUG
            printf("%d %d %dn", op_l, op_r, k);
#endif
//#ifndef LOCAL_DEBUG_NOUT
            printf("%dn", block_prev(op_l - 1, op_r - 1, k));
//#endif
        }
        else if (op == OP_NEXT)
        {
            read(op_l);
            read(op_r);
            read(k);
#ifdef LOCAL_DEBUG
            printf("%d %d %dn", op_l, op_r, k);
#endif
//#ifndef LOCAL_DEBUG_NOUT
            printf("%dn", block_next(op_l - 1, op_r - 1, k));
//#endif
        }
#ifdef LOCAL_DEBUG_NOUT
        checker();
#endif
    }
#ifdef LOCAL_TIME
    printf("run time: %lld msn", clock() - start_time_);
#endif
#ifdef READ_FILE
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}
#else
int main()
{
    freopen("3196.in", "r", stdin);
    freopen("3196simp.out", "w", stdout);
    fread_point = getchar();
    read(n);
    read(m);
    for (int i = 0; i < n; i++)
    {
        read(init_read[i]);
        num_max = std::max(num_max, init_read[i]);
        num_min = min(num_min, init_read[i]);
    }
    for (int i = 0; i < m; i++)
    {
        read(op);
#ifdef LOCAL_DEBUG
        printf("%d %d ", i, op);
#endif
        if (op == OP_Q_RANK)
        {
            read(op_l);
            read(op_r);
            read(k);
#ifdef LOCAL_DEBUG
            printf("%d %d %dn", op_l, op_r, k);
#endif
        }
        else if (op == OP_Q_NUM)
        {
            read(op_l);
            read(op_r);
            read(k);
#ifdef LOCAL_DEBUG
            printf("%d %d %dn", op_l, op_r, k);
#endif
        }
        else if (op == OP_CHANGE)
        {
            read(op_l);
            read(k);
            num_max = std::max(num_max, k);
            num_min = min(num_min, k);
#ifdef LOCAL_DEBUG
            printf("%d %dn", op_l, k);
#endif
            init_read[op_l - 1] = k;
        }
        else if (op == OP_PREV)
        {
            read(op_l);
            read(op_r);
            read(k);
#ifdef LOCAL_DEBUG
            printf("%d %d %dn", op_l, op_r, k);
#endif
            int max_num = -1;
            for (int i = op_l - 1; i < op_r; i++)
            {
                if (init_read[i] < k)
                {
                    max_num = std::max(max_num, init_read[i]);
                }
            }
            printf("%dn", max_num);
        }
        else if (op == OP_NEXT)
        {
            read(op_l);
            read(op_r);
            read(k);
#ifdef LOCAL_DEBUG
            printf("%d %d %dn", op_l, op_r, k);
#endif
            int min_num = -1;
            for (int i = op_l - 1; i < op_r; i++)
            {
                if (init_read[i] > k)
                {
                    min_num = min(min_num, init_read[i]);
                }
            }
            printf("%dn", min_num);
        }
        for (int j = 0; j < n; j++)
        {
            printf("%d ", init_read[j]);
        }
        printf("n");
    }
    fclose(stdin);
    fclose(stdout);
}
#endif