zoukankan      html  css  js  c++  java
  • 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;
            }
        }
    }

  • 相关阅读:
    jvM垃圾回收
    Java快速失败和安全失败
    方法覆盖和方法重载
    leetcode-Reverse Words in a String
    自己玩玩
    leetcode-Reverse Vowels of a String
    leetcode-Reverse String
    leetcode-Multiply Strings
    java多线程-cas及atomic
    @media响应式布局
  • 原文地址:https://www.cnblogs.com/Cooook/p/7738514.html
Copyright © 2011-2022 走看看