3065: 带插入区间K小值 树套树 + 替罪羊树 + 权值线段树

经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题.

Code:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
// 带插入区间 k 小值
// 外层:替罪羊
// 内层:权值线段树
using namespace std;
#define setIO(s) freopen(s".in","r",stdin), freopen(s".out","w",stdout) 
#define debug()  printf("OK
") 
#define maxn 11005000
#define N 70002
int n,lastans;
struct Segment_Tree{
    struct Node{
        int ls,rs,siz; 
        Node(int ls=0,int rs=0,int siz=0):ls(ls),rs(rs),siz(siz){}
    }node[maxn];
    queue<int>Q; 
    void init(){ for(int i=1;i<maxn;++i) Q.push(i); }
    void newnode(int &o) { o=Q.front(), Q.pop(); }
    void update(int l,int r,int &o,int pos,int delta){
        if(!o) newnode(o); 
        node[o].siz+=delta;
        if(!node[o].siz) { dfs(o); return; }
        if(l==r) return;
        int mid=(l+r)>>1;
        if(pos<=mid) update(l,mid,node[o].ls,pos,delta);
        else update(mid+1,r,node[o].rs,pos,delta);
    }
    void dfs(int &o){
        if(!o)return;
        dfs(node[o].ls),Q.push(o),dfs(node[o].rs);
        node[o].siz=0;
        o=0; 
    }
}segin;
struct Binary_Search_Tree{
    inline bool check(int son,int o){
        if(son*10>=o*9) return true; 
        return false; 
    }
    int cnt,root;
    int seq[N],count[3]; 
    vector<int>re;
    struct Node{
        int ls,rs,siz,root,cur,val; 
        Node(int ls=0,int rs=0,int siz=0,int root=0,int cur=0,int val=0):ls(ls),rs(rs),root(root),cur(cur),val(val){}
    }node[maxn];
    inline void newnode(int &o,int val){  o=++cnt,node[o].val=val,node[o].siz=1;  }
    void dfs(int &o){
        if(!o) return;
        segin.dfs(node[o].root),segin.dfs(node[o].cur); 
        dfs(node[o].ls),re.push_back(o),dfs(node[o].rs);
        node[o].siz=0;
        o=0;

    }
    void construct(int l,int r,int &o){
        if(l>r)return;
        int mid=(l+r)>>1;
        o=re[mid];
 
        for(int i=l;i<=r;++i) 
            segin.update(0,N,node[o].root,node[re[i]].val,1);
 
        segin.update(0,N,node[o].cur,node[o].val,1);  
        if(l==r){ node[o].siz=1; return; } 
 
        construct(l,mid-1,node[o].ls), construct(mid+1,r,node[o].rs); 
        node[o].siz=node[node[o].ls].siz+node[node[o].rs].siz+1; 
    }
    inline void Rebuild(int &o){  re.clear(),dfs(o),construct(0,re.size()-1,o);   }
    void insert(int &o,int k,int val,bool is){
        if(!o){
            newnode(o,val),segin.update(0,N,node[o].root,val,1),segin.update(0,N,node[o].cur,val,1); 
            return;
        }
        ++node[o].siz, segin.update(0,N,node[o].root,val,1);
        bool tag; 
        if(k<=node[node[o].ls].siz+1) tag=check(node[node[o].ls].siz+1,node[o].siz), insert(node[o].ls,k,val,is||tag);
        else tag=check(node[node[o].rs].siz+1,node[o].siz), insert(node[o].rs,k-node[node[o].ls].siz-1,val,is||tag);
        if(!is&&tag)  Rebuild(o); 
    }
    int modify(int o,int pos,int delta){
        int num;
        if(pos==node[node[o].ls].siz+1) {
            segin.update(0,N,node[o].root,node[o].val,-1),segin.dfs(node[o].cur),node[o].cur=0; 
            segin.update(0,N,node[o].root,delta,1),segin.update(0,N,node[o].cur,delta,1);
            num=node[o].val,node[o].val=delta;
            return num;
        }
        if(pos<=node[node[o].ls].siz) num=modify(node[o].ls,pos,delta);
        else num=modify(node[o].rs,pos-node[node[o].ls].siz-1,delta);
        segin.update(0,N,node[o].root,num,-1),segin.update(0,N,node[o].root,delta,1); 
        return num; 
    }
    void Build(){
        scanf("%d",&n),re.clear();
        int tmp,x ;
        for(int i=1;i<=n;++i)
            scanf("%d",&tmp),newnode(x,tmp),re.push_back(x);
        construct(0,re.size()-1,root);  
    }
    void Get(int l,int r,int o,int L,int R){ 
        if(l>R||r<L||l>r||!o)return;
        if(l>=L&&r<=R) {  seq[++count[0]]=node[o].root; return;  } 
        int mid=node[node[o].ls].siz+l;                         
        if(mid>=L&&mid<=R&&mid<=r) seq[++count[0]]=node[o].cur;                          
        Get(l,mid-1,node[o].ls,L,R),Get(mid+1,r,node[o].rs,L,R); 
    }
    int solve(int l,int r,int k){
        if(l==r) return l;
        int lsum=0; 
        for(int i=1;i<=count[0];++i) {
            lsum+=segin.node[segin.node[seq[i]].ls].siz; 
        }
        int mid=(l+r)>>1;
        if(k>lsum) 
        {
            for(int i=1;i<=count[0];++i) seq[i]=segin.node[seq[i]].rs; 
            return solve(mid+1,r,k-lsum); 
        }
        else
        {
            for(int i=1;i<=count[0];++i)seq[i]=segin.node[seq[i]].ls; 
            return solve(l,mid,k); 
        }
    }
    void Insert(){
        int a,b;
        ++n,scanf("%d%d",&a,&b),a^=lastans,b^=lastans,insert(root,a,b,0); 
    }
    void Modify(){
        int a,b;
        scanf("%d%d",&a,&b),a^=lastans,b^=lastans,modify(root,a,b);
    } 
    int Query(){
        int L,R,k;
        count[0]=0, scanf("%d%d%d",&L,&R,&k),L^=lastans,R^=lastans,k^=lastans; 
        if(L>R)swap(L,R); 
        Get(1,n,root,L,R);
        return solve(0,N,k); 
    }
}BST;
int main(){
    //setIO("input");
    segin.init(), BST.Build(); 
    char opt[10];
    int q;
    scanf("%d",&q);
    while(q--){
        scanf("%s",opt); 
        if(opt[0]=='I') BST.Insert();
        if(opt[0]=='M') BST.Modify();  
        if(opt[0]=='Q') printf("%d
",lastans=BST.Query());
    } 
    return 0;
} 

  

原文地址:https://www.cnblogs.com/guangheli/p/10133888.html