P2617 Dynamic Rankings

题目描述

给定一个含有 n 个数的序列 a1,a2…an,需要支持两种操作:

  • Q l r k 表示查询下标在区间 [l,r] 中的第 k 小的数
  • C x y 表示将 \(a_x\) 改为 y

输入格式

第一行两个正整数 n,m,表示序列长度与操作个数。
第二行 n 个整数,表示 a1,a2…an​。
接下来 m 行,每行表示一个操作,都为上述两种中的一个。

输出格式

对于每一次询问,输出一行一个整数表示答案。

输入输出样例

输入 #1

5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

输出 #1

3
6

说明/提示

【数据范围】

​ 对于 100% 的数据,\(1\le n,m \le 10^5,1 \le l \le r \le n,1 \le k \le r-l+1,1\le x \le n,0 \le a_i,y \le 10^9\)

#include <bits/stdc++.h>
    
using namespace std;
    
inline long long read() {
    long long s = 0, f = 1; char ch;
    while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    return s * f;
}
    
const int N = 2e5 + 5, inf = 1e9;
int n, m, cnt, tot; 
int a[N], t[N], ans[N];   
struct que { int x, y, z, opt; } q[N << 2], ql[N << 2], qr[N << 2];

int lowbit(int x) { return x & (-x); }

void change(int x, int y) { for(; x <= N - 5; x += lowbit(x)) t[x] += y; } 

int ask(int x) { int res = 0; for(; x ; x -= lowbit(x)) res += t[x]; return res; }

void work(int L, int R, int l, int r) {
    if(l > r) return ;
    if(L == R) {
        for(int i = l;i <= r; i++) ans[q[i].opt] = L;
        return ;
    }
    int mid = (L + R) >> 1;
    int tmp1 = 0, tmp2 = 0; 
    for(int i = l;i <= r; i++) {
        if(q[i].opt <= 0) {
            if(q[i].y <= mid) change(q[i].x, q[i].z), ql[++tmp1] = q[i];
            else qr[++tmp2] = q[i];
        }
        else {
            int tmp = ask(q[i].y) - ask(q[i].x - 1);
            if(tmp >= q[i].z) ql[++tmp1] = q[i];
            else q[i].z -= tmp, qr[++tmp2] = q[i];
        }
    }
    for(int i = l;i <= r; i++) 
        if(q[i].opt <= 0 && q[i].y <= mid) change(q[i].x, -q[i].z);
    for(int i = 1;i <= tmp1; i++) q[l + i - 1] = ql[i];
    for(int i = 1;i <= tmp2; i++) q[l + tmp1 + i - 1] = qr[i];
    work(L, mid, l, l + tmp1 - 1); work(mid + 1, R, l + tmp1, r);
}

int main() {
    
    n = read(); m = read();
    for(int i = 1, x; i <= n; i ++) {
        x = read(); a[i] = x;
        q[++cnt].opt = 0; q[cnt].x = i; q[cnt].y = x; q[cnt].z = 1;
    }
    for(int i = 1, l, r, k;i <= m; i++) {
        char ch; cin >> ch;
        if(ch == 'Q') {
            l = read(); r = read(); k = read();
            q[++cnt].opt = ++tot; q[cnt].x = l; q[cnt].y = r; q[cnt].z = k;
        }
        if(ch == 'C') {
            l = read(); r = read(); 
            q[++cnt].opt = -1; q[cnt].x = l; q[cnt].y = a[l]; q[cnt].z = -1;
            q[++cnt].opt = 0; q[cnt].x = l; q[cnt].y = r; q[cnt].z = 1;
            a[l] = r;
        }
    }

    work(-inf, inf, 1, cnt);
    for(int i = 1;i <= tot; i++) printf("%d\n", ans[i]);

    return 0;
}
posted @ 2020-09-06 21:50  C锥  阅读(145)  评论(0编辑  收藏  举报