BZOJ1901 ZOJ2112 Dynamic Rankings

Title:

Single point modification, the interval K is large

answer

I don't know how to chair the tree, but I use the overall divide and conquer based on the range .

For modification, it can be divided into two operations, one is to undo and the other is to add.

There are three operations in total

When op=-1, it means cancel, and x means position;

When op=0, it means increase, insert y at position x;

When op>0, it represents the query, and the z-th largest in the interval [x,y]. (X=l, y=r, z=k)

When dividing and conquering according to the range,

When op=0 and q[i].y<=mid, it is inserted normally. But note that at this time, regardless of the size of q[i].y, a[q[i].x]=i is required, and the q[i].x bit of the actual sequence is q[i]. This is because when there is an operation to modify the position of the sequence a[e] to f, then the first step is to delete a[e] first, then it is necessary to judge a[e]<=mid, if If it is true, a[e] needs to be deleted from the tree array; if it is false, it is fine.

 

It is also worth thinking about whether the revocation and addition are placed in lq or rq .

Before the modification, a[l~r] has been initialized.

When facing "C i t", split it into q[j]={op=-1,x=i},q[j+1]={op=0,x=i,y=t}.

When a[i]<=mid, t<=mid: q[j] and q[j+1] are both placed in lq.

When a[i]<=mid,t>mid: When the subsequent value range is less than mid, a[i] will still be withdrawn, so q[j] is placed in lq. And q[j+1] can be directly thrown to rq, because when performing the divide and conquer of the following value range> mid, for the operation after j+1, a[i]<=mid,q[j] two operations It is meaningless, only q[j+1] is meaningful, so you can put t directly at the i position, that is, only put q[j+1] into rq.

When a[i]>=mid, t>=mid: It has no effect on the current divide and conquer, and both q[j] and q[j+1] are placed in rq.

When a[i]>=mid,t<mid: For the current divide and conquer, the operation of a[i]>=mid,q[j] is meaningless, and it can be directly q[j+1], so The operation of a[i] initialization and q[j] are directly thrown into rq, and q[j] is initialized as a[i].

 

 

#include <cstdio>
#include <iostream>
#include <vector>                                                                                                                                 
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <cstdlib>
#define pb push_back 
#define fir first 
#define sec second
#define All(x) (x).begin(),(x).end() 
#define ms(a,b) memset((a),(b),sizeof(a)) 
#define INF 0x3f3f3f3f
#define sp system("pause")
#define multi int T;scanf("%d",&T);while((T)--) 
using namespace std;
typedef long long ll;
typedef double db;
const int N=2e4+5;
const int mod=10007;
const db pi=acos(-1.0);
int n,m;
struct  node{
    int op,x,y,z;
}q[N<<1],lq[N<<1],rq[N<<1];
int tr[N],ans[N],a[N];
inline int ask(int x){int res=0;for(int i=x;i>0;i-=i&-i) res+=tr[i]; return res;}
inline void add(int x,int val) {for(int i=x;i<=n;i+=i&-i) tr[i]+=val;}
inline void clear(int x){for(int i=x;i<=n;i+=i&-i) tr[i]=0;}
void solve(int lval,int rval,int l,int r){
    if(l>r) return ;
    if(lval==rval){
        for(int i=l;i<=r;i++) if(q[i].op>0) ans[q[i].op]=lval;
        return ;
    }
    int mid=(lval+rval)>>1,rt=0,lt=0;
    for(int i=l;i<=r;i++){
        if(q[i].op==0){
            if(q[i].y<=mid){
                add(q[i].x,1);
                lq[++lt]=q[i];
            }else rq[++rt]=q[i];
            a[q[i].x]=i;//q[i].y>mid也要给a,可能这个位置经过多次改变,每次更新a,知道这一位到底>mid,还是<=mid
        }else{
            if(q[i].op==-1){
                int pos=a[q[i].x];
                if(q[pos].y<=mid) {
                    lq[++lt]=q[i];
                    add(q[pos].x,-1);
                }else rq[++rt]=q[i];
            }else{
                int cnt=ask(q[i].y)-ask(q[i].x-1);
                if(cnt>=q[i].z) lq[++lt]=q[i];
                else{
                    q[i].z-=cnt;
                    rq[++rt]=q[i];
                }
            }
        }
    }
    for(int i=l;i<=r;i++){
        if(q[i].op==0&&q[i].y<=mid) clear(q[i].x);
        // if(q[i].op==-1){//此时a存储的已经不是最早对应的了
        //     int pos=a[q[i].x];
        //     if(q[pos].y<=mid) add(q[pos].x,1);
        // }
    }
    for(int i=1;i<=lt;i++) q[l+i-1]=lq[i];
    for(int i=1;i<=rt;i++) q[l+lt+i-1]=rq[i];
    solve(lval,mid,l,l+lt-1);
    solve(mid+1,rval,l+lt,r);
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("D:\\work\\data.in","r",stdin);
    #endif
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&q[i].y);
        q[i].x=i;
        q[i].op=0;
    }
    char op[5];
    int t=n,anst=0;
    for(int i=1;i<=m;i++){
        ++t;
        scanf("%s%d%d",op,&q[t].x,&q[t].y);
        if(op[0]=='Q'){
            scanf("%d",&q[t].z);
            q[t].op=++anst;
        }else{
            q[t].op=-1;
            ++t;
            q[t].op=0;
            q[t].x=q[t-1].x;
            q[t].y=q[t-1].y;
        }
    }
    solve(-INF,INF,1,t);
    for(int i=1;i<=anst;i++) printf("%d\n",ans[i]);
}

 

Guess you like

Origin blog.csdn.net/Luowaterbi/article/details/109002632