BZOJ 3065: 带插入区间K小值

题目大意:rt,维护一个数据结构 ,支持带插入区间K小值

如果不带插入的话,就BIT+主席树,而带了插入,所以外面只能套一个平衡树,而splay和treap什么还要一直转,TLE是稳稳的,那么我们就选择了替罪羊树,因为不用转,然后重建的时候暴力重构就好了,那么对于修改来说先在内层线段树中删除再加入就好了,而k小值就是二分答案就好了,不过还是码的心累啊。

code:

#define MAXN 1401000
#define inf 70000
#include <iostream>
#include <vector>
#include <stdio.h>
#include <algorithm>
using namespace std;
int n,q,len,last_ans,li[MAXN],num;
int val_used[MAXN],Num;
const double alpha = 0.755;

template<typename _t>
inline _t read(){
    _t x=0;
    int f=1;
    char ch=getchar();
    for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f=-f;
    for(;ch<='9'&&ch>='0';ch=getchar())x=x*10+(ch^48);
    return (_t)x*f;
}

//Segment Tree
struct Tree{
    Tree *ls,*rs;
    int s,l,r,m;
 
    void *operator new (size_t);
    void operator delete (void *p);
 
    Tree(int x,int y);
 
    Tree(){
        s=0;
        ls=rs=NULL;
        l=r=m=0;
    }
}*S,*T,*used[MAXN],*Nil=new Tree();
 
Tree :: Tree(int x,int y){
    l=x;r=y;
    m=l+r>>1;
    ls=rs=Nil;
    s=0;
}
 
vector<Tree*>bin;
 
void* Tree :: operator new (size_t){
    Tree *p;
    if(!bin.empty()){
        p=bin.back();
        bin.pop_back();
    }
    else{
        if(S==T){
            S=new Tree[1<<15];
            T=S+(1<<15);
        }
        p=S++;
    }
    return p;
}
 
void Tree :: operator delete (void *p){
    bin.push_back((Tree*)p);
}
 
struct node{
    node *ls,*rs;
    Tree *root;
    int s,v;
 
    inline void Maintain(){
        s=ls->s+rs->s+1;
    }
 
    inline bool bad(){
        return ls->s>s*alpha||rs->s>s*alpha;
    }
     
    void* operator new (size_t);
    void operator delete (void *p);
 
    node(){
        s=0;v=0;
        root=Nil;
        ls=rs=NULL;
    }
 
    node(int x);
}*null=new node(),*C,*mempool,*lst[MAXN],*root;
 
vector<node*>Stack;
 
node :: node(int x){
    s=1;v=x;
    root=Nil;
    ls=rs=null;
}
 
void* node :: operator new (size_t){
    node *p;
    if(!Stack.empty()){
        p=Stack.back();
        Stack.pop_back();
    }
    else{
        if(C==mempool){
            C=new node[1<<15];
            mempool=C+(1<<15);
        }
        p=C++;
    }
    return p;
}
 
void node :: operator  delete (void *p){
    Stack.push_back((node*)p);
}
 
inline int Rank(Tree *o,int x){
    int ans = 0;
    while(o!=Nil){
        if(o->l==o->r)return ans;
        if(x<=o->m)o=o->ls;
        else ans+=o->ls->s,o=o->rs;
    }
    return ans;
}
 
void Tree_insert(Tree *&o,int l,int r,int val){
    if(o==Nil)o=new Tree(l,r);
    o->s++;
    if(l==r)return;
    if(val<=o->m)Tree_insert(o->ls,l,o->m,val);
    else Tree_insert(o->rs,o->m+1,r,val);
}
 
void dfs(Tree *&o){
    if(o==Nil)return;
    dfs(o->ls);
    dfs(o->rs);
    delete o;
}
 
void travel(node *o){
    if(o==null)return;
    travel(o->ls);
    lst[++len]=o;
    li[len]=o->v;
    dfs(o->root);
    o->root=Nil;
    travel(o->rs);
}
 
node* divide(int l,int r){
    if(l>r)return null;
    int m=l+r>>1;
    for(int i=l;i<=r;i++)Tree_insert(lst[m]->root,0,inf,li[i]);
    lst[m]->ls=divide(l,m-1);
    lst[m]->rs=divide(m+1,r);
    lst[m]->Maintain();
    return lst[m];
} 
 
void rebuild(node *&o){
    len=0;
    travel(o);
    o=divide(1,len);
}
 
node ** insert(node *&o,int pos,int w){
    if(o==null){
        o=new node(w);
        Tree_insert(o->root,0,inf,w);
        return &null;
    }
    Tree_insert(o->root,0,inf,w);
    node **p;
    if(pos<=o->ls->s+1)p=insert(o->ls,pos,w);
    else p=insert(o->rs,pos-o->ls->s-1,w);
    if(o->bad())p=&o;
    o->Maintain();
    return p;
}
 
void Insert(int pos,int w){
    node **p=insert(root,pos,w);
    if(*p!=null)rebuild(*p);
}
 
void Tree_erase(Tree *&o,int w){
    o->s--;
    if(o->l==o->r){
        if(o->s==0)delete o,o=Nil;
        return;
    }
    if(w<=o->m)Tree_erase(o->ls,w);
    else Tree_erase(o->rs,w);
    if(!o->s)delete o,o=Nil;
}
 
void erase(node *o,int pos,int w){
    Tree_erase(o->root,w);
    if(pos==o->ls->s+1)return;
    if(pos<=o->ls->s)erase(o->ls,pos,w);
    else erase(o->rs,pos-o->ls->s-1,w);
}
 
void get_Tree(node *o,int l,int r){
    if(o==null)return;
    if(l<=1&&o->s<=r){
        used[++num]=o->root;
        return;
    }
    if(l<=o->ls->s)get_Tree(o->ls,l,r);
    if(l<=o->ls->s+1&&r>=o->ls->s+1)val_used[++Num]=o->v;
    if(o->ls->s+1<r)get_Tree(o->rs,l-o->ls->s-1,r-o->ls->s-1);
}
 
int get_rank(int x){
    int ans = 0;
    for(int i=1;i<=num;i++)
        ans+=Rank(used[i],x);
    for(int i=1;i<=Num;i++)
        if(val_used[i]<x)ans++;
        else break;
    return ans;
}
 
void Query(){
    int l=read<int>()^last_ans,r=read<int>()^last_ans,k=read<int>()^last_ans;
    num=Num=0;
    get_Tree(root,l,r);
    sort(val_used+1,val_used+1+Num);
    int L=0,R=inf,ans;
    while(L<=R){
        int mid = L+R>>1;
        if(get_rank(mid)+1<=k)ans=mid,L=mid+1;
        else R=mid-1;
    }
    last_ans=ans;
    printf("%d
",ans);
}
 
int __read_char(){
    char ch=getchar();
    for(;ch!='M'&&ch!='I'&&ch!='Q';ch=getchar());
    if(ch=='Q')return 1;
    if(ch=='I')return 2;
    return 3;
}
 
void __insert(){
    int pos=read<int>()^last_ans,val=read<int>()^last_ans; 
    Insert(pos,val);
}
 
inline int __find_val(int pos){
    node *p=root;
    while(p!=null){
        if(p->ls->s+1==pos)return p->v;
        else if(p->ls->s>=pos)p=p->ls;
        else pos-=p->ls->s+1,p=p->rs;
    }
}
 
void __change(node *o,int pos,int val){
    Tree_insert(o->root,0,inf,val);
    if(pos==o->ls->s+1){
        o->v=val;
        return;
    }
    if(pos<=o->ls->s)__change(o->ls,pos,val);
    else __change(o->rs,pos-o->ls->s-1,val);
}
 
void change(){
    int pos=read<int>()^last_ans,val=read<int>()^last_ans;
    erase(root,pos,__find_val(pos));
    __change(root,pos,val);
}
 
void __dfs(node *root){
    if(root==null)return;
    __dfs(root->ls);
    printf("%d ",root->v);
    __dfs(root->rs);
}//debug
 
int main(){
    root = null;
    n=read<int>();
    for(int i=1;i<=n;i++)li[i]=read<int>(),lst[i]=new node(li[i]);
    root = divide(1,n);
    int Q = read<int>();
    while(Q--){
        int op=__read_char();
        switch(op){
            case 1:Query();break;
            case 2:__insert();break;
            case 3:change();break;
        }
    }
}

原文地址:https://www.cnblogs.com/Cooook/p/7738514.html