BZOJ 3065: 带插入区间K小值

来源:互联网 发布:蓝牙怎么传软件 编辑:程序博客网 时间:2024/05/17 17:38

题目大意: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 Treestruct 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\n",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;        }    }}

原创粉丝点击