ZOJ - 2112 Dynamic Rankings

Nightmare丶發表於2020-12-24
題解:

對於區間詢問,能夠很快的轉移,考慮莫隊,因為帶修改,所以加一維修改時間做帶修莫隊,至於區間第k小,考慮權值線段樹或者主席樹,這裡帶修改,所以我們選擇將所有值離散化,用權值線段樹求區間第k小即可

程式碼:
/*
 * @Author : Nightmare
 */
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define ld long double
#define ls 2 * rt
#define rs 2 * rt + 1
#define PII pair<int,int>
#define PDD pair<double, double>
#define gcd(a,b) __gcd(a,b)
#define lowbit(x) (x & (-x))
const int N = 5e4 + 5;
const int M = 6e4 + 5;
const int mod = 1e9 + 7;
int n, m, sz, a[N], blk[N], ans[N], sum[M << 2];
struct Query{
    int l, r, k, id, ti;
    bool operator < (Query &b) const{
        if(blk[l] != blk[b.l]) return blk[l] < blk[b.l];
        if(blk[r] != blk[b.r]) return blk[r] < blk[b.r];
        return ti < b.ti;
    }
}que[N];
struct Modify{ int pos, val; }C[N];
void build(int rt, int l, int r){
    if(l == r){ sum[rt] = 0; return ; }
    int mid = (l + r) >> 1;
    build(ls, l, mid); build(rs, mid + 1, r);
    sum[rt] = sum[ls] + sum[rs];
}
void change(int rt, int l, int r, int qp, int qv){
    if(l == r){ sum[rt] += qv; return ; }
    int mid = (l + r) >> 1;
    if(qp <= mid) change(ls, l, mid, qp, qv);
    else change(rs, mid + 1, r, qp, qv);
    sum[rt] = sum[ls] + sum[rs];
}
int kth(int rt, int l, int r, int k){
    if(sum[rt] < k) return -1;
    if(l == r) return l;
    int mid = (l + r) >> 1;
    if(k > sum[ls]) return kth(rs, mid + 1, r, k - sum[ls]);
    else return kth(ls, l, mid, k);
}
void add(int x){ change(1, 1, sz, x, 1); }
void del(int x){ change(1, 1, sz, x, -1); }
void upd(int x, int i){
    if(C[x].pos >= que[i].l && C[x].pos <= que[i].r) add(C[x].val), del(a[C[x].pos]);
    swap(a[C[x].pos], C[x].val);
}
void solve(){
    scanf("%d %d", &n, &m); vector<int> vec; int sq = pow(n, 0.666);
    for(int i = 1 ; i <= n ; i ++) scanf("%d", &a[i]), vec.push_back(a[i]), blk[i] = (i - 1) / sq;
    int qtot = 0, ctot = 0;
    for(int i = 1 ; i <= m ; i ++){
        char op; int x, y, z; scanf(" %c %d %d", &op, &x, &y);
        if(op == 'Q') scanf("%d", &z), ++ qtot, que[qtot] = {x, y, z, qtot, ctot};
        else if(op == 'C') C[++ ctot] = {x, y}, vec.push_back(y);
    }
    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end()), vec.end());
    sz = vec.size();
    build(1, 1, sz);
    for(int i = 1 ; i <= n ; i ++) a[i] = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin() + 1;
    for(int i = 1 ; i <= ctot ; i ++) C[i].val = lower_bound(vec.begin(), vec.end(), C[i].val) - vec.begin() + 1;
    sort(que + 1, que + qtot + 1);
    for(int i = 1, l = 1, r = 0, t = 0 ; i <= qtot ; i ++){
        int L = que[i].l, R = que[i].r, T = que[i].ti;
        while(l < L) del(a[l ++]);
        while(r < R) add(a[++ r]);
        while(l > L) add(a[-- l]);
        while(r > R) del(a[r --]);
        while(t < T) upd(++ t, i);
        while(t > T) upd(t --, i);
        ans[que[i].id] = vec[kth(1, 1, sz, que[i].k) - 1];
    }
    for(int i = 1 ; i <= qtot ; i ++) printf("%d\n", ans[i]);
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen("E:\\in.txt", "r", stdin);
#endif
    int T; cin >> T; while(T --) solve();
#ifndef ONLINE_JUDGE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

相關文章