P2617 Dynamic Rankings(整体二分)

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2617 Dynamic Rankings(整体二分)相关的知识,希望对你有一定的参考价值。

P2617 Dynamic Rankings

题意:

在这里插入图片描述
待修改的区间最值问题

题解:

整体二分天然带有修改性
整体二分做不带修改的区间最值—>看这里
现在待修改,我们可以将第l位修改为x,因为我们是用树状数组来维护的,所以把这个过程拆分成将第l个数删去,再将第l个数加上,但是这两个第l数所指的值是不一样的,因为我们是判断,只有值<=mid的数才插入到树状数组中,虽然是同一个位置,但是因为可能改了值导致原本插入,现在不插入,也有可能相反,这样就实现了修改操作,其实还是要把整体二分的原理搞清楚就懂了
比如:当然mid = 3
第L位原本是2现在改成4
一开始第L位是插入到树状数组的(因为2<mid)(读入数据时的操作),然后先将第L位删去(修改操作分离出的删去操作),然后判断现在值是否满足要求,发现不满足(4>mid=3),则不插入到树状数组,这样一套,就完成了修改

代码:

#pragma optimize("Ofast")
#include<bits/stdc++.h>
#define MAXN 300005
#define inf int(1e9)
using namespace std;
typedef long long ll;

int N,M;
int a[MAXN];

struct Node{
    int op,x,y,k;//op=insert+1/remove-1,query2
    int id;
    Node(int op=0, int x=0, int y=0, int k=0, int id=0):op(op), x(x), y(y), k(k), id(id){}
} q[MAXN],lq[MAXN],rq[MAXN];

//
int fw[MAXN];
inline int lbt(int x){
    return x&(-x);
}

inline void change(int x, int dv){
    for(;x<=N;x+=lbt(x)){
        fw[x] += dv;
    }
}

inline int query(int x){
    int ans = 0;
    for(;x>0;x-=lbt(x)){
        ans += fw[x];
    }
    return ans;
}
//
int ANS[MAXN];

void solve(int vl, int vr, int ql, int qr){
    //cerr<<"solve: "<<vl<<" "<<vr<<" "<<ql<<" "<<qr<<endl;
    if(ql > qr) return;
    if(vl == vr){
        for(int i=ql;i<=qr;i++){
            if(q[i].op==2) ANS[q[i].id] = vl;
        }
        return;
    }
    //insert
    int mid = (vl + vr)>>1;
    int nl = 0, nr = 0;
    for(int i=ql;i<=qr;i++){
        if(q[i].op != 2){//insert/remove
            if(q[i].x <= mid) change(q[i].y, q[i].op), lq[++nl] = q[i];
            else rq[++nr] = q[i];
        }
        else{//query
            int n = query(q[i].y) - query(q[i].x-1);
            if(q[i].k <= n) lq[++nl] = q[i];
            else{
                q[i].k -= n;
                rq[++nr] = q[i];
            }
        }
    }

    //remove
    for(int i=ql;i<=qr;i++){
        if(q[i].op != 2){
            if(q[i].x <= mid) change(q[i].y, -q[i].op);
        }
    }

    for(int i=1;i<=nl;i++) q[ql+i-1] = lq[i];
    for(int i=1;i<=nr;i++) q[ql+nl+i-1] = rq[i];
    solve(vl, mid, ql, ql+nl-1);
    solve(mid+1, vr, ql+nl, qr);
}

int main(){
    scanf("%d%d", &N, &M);

    int NN = 0, Q = 0; 
    int x,l,r,k;
    for(int i=1;i<=N;++i){
        scanf("%d", &a[i]);
        q[++NN] = Node(1,a[i],i);
    }

    char op[5];
    for(int i=1;i<=M;i++){
        scanf("%s", op);
        if(op[0]=='Q'){
            scanf("%d%d%d", &l, &r, &k);
            q[++NN] = Node(2,l,r,k,++Q);
        } 
        else{
            scanf("%d%d", &l, &x);
            q[++NN] = Node(-1,a[l],l);
            q[++NN] = Node(+1,x,l);
            a[l] = x;
        }
    }

    solve(-1e9,1e9,1,NN);
    for(int i=1;i<=Q;i++){
        printf("%d\\n", ANS[i]);
    }
    return 0;
}

以上是关于P2617 Dynamic Rankings(整体二分)的主要内容,如果未能解决你的问题,请参考以下文章

P2617 Dynamic Rankings(主席树+树状数组)

bzoj P2617 Dynamic Rankings

P2617 Dynamic Rankings

P2617 Dynamic Rankings

P2617 Dynamic Rankings(带修主席树)

P2617 Dynamic Rankings(动态区间第k小)