BZOJ4552

7 篇文章 0 订阅

O(nlogn),可分裂合并的线段树

嗨呀,写死我了

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>
#define Sum(a) ((a)?(a)->sum:0)
using namespace std;
struct tree{
    tree* l,* r;
    int sum;
    tree(){l=r=0;sum=0;}
    void update(){
        sum=Sum(l)+Sum(r);
    }
};
 
struct data{
    int l,r,type;
    tree* ptr;
    data(int l,int r,int type,tree*ptr):
        l(l),r(r),type(type),ptr(ptr){}
    int operator<(const data& d)const{
        return r<d.r;
    }
};
typedef set<data>::iterator sit;
tree* merge(tree*& a,tree* b,int l,int r){
//  printf("[%d,%d]",a,b);
    if(!a)return b;
    if(!b)return a;
    if(l==r){
        a->sum+=b->sum;
        return a;
    }
    int mid=l+r>>1;
    a->l=merge(a->l,b->l,l,mid);
    a->r=merge(a->r,b->r,mid+1,r);
    a->update();
    return a;
}
tree* split(tree*& a,int l,int r,int k){
     
    if(!k||!a)return 0;
//  printf(" S{%d,%d,%d}",a,l,r);
    if(l==r){
        tree* ret=new tree;
        ret->sum=a->sum;
        a=0;
        return ret;
    }
    tree* ret=new tree;
    int mid=l+r>>1;
    if(Sum(a->l)<k){
        tree* f=split(a->r,mid+1,r,k-Sum(a->l));
        ret->r=f,ret->l=a->l,a->l=0;
//      printf("[%d,%d,%d]",a->l,f,k);
        ret->update();
        a->update();
    } else {
        tree* f=split(a->l,l,mid,k);
        ret->l=f,ret->r=0;
        ret->update();
        a->update();
    }
//  printf("{%d}\n",k);
    return ret;
}
void insert(tree*& a,int l,int r,int k){
    if(!a)a=new tree;
    a->sum++;
    if(l==r)return ;
    int mid=l+r>>1;
    if(k<=mid)insert(a->l,l,mid,k);
    else insert(a->r,mid+1,r,k);
}
int ask(tree* a,int l,int r,int k){
//  printf("[%d,%d]",a->sum,k);
    if(l==r)return l;
    int mid=l+r>>1;
    if(Sum(a->l)<k)return ask(a->r,mid+1,r,k-Sum(a->l));
    else return ask(a->l,l,mid,k);
}
tree* newnode(int k,int n){
    tree* ret=0;
    insert(ret,1,n,k);
    return ret;
}
void print(tree* a,int l,int r,bool type){
    if(!a)return ;
    if(l==r){
        printf("%d ",l);
        return ;
    }
    int mid=l+r>>1;
    if(type){
        print(a->r,mid+1,r,type);
        print(a->l,l,mid,type);
    } else {
        print(a->l,l,mid,type);
        print(a->r,mid+1,r,type);    
    }
}
int n,m;
set<data>st;
int main(){
//  freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1,a;i<=n;++i)
        scanf("%d",&a),st.insert(data(i,i,0,newnode(a,n)));
    for(int i=1,k,op,l,r;i<=m;++i){
        scanf("%d%d%d",&op,&l,&r);
        tree* res=0;
        sit it=st.lower_bound(data(0,l,0,0));
        while(it!=st.end()&&it->l<=r){
            data d=*it;
            sit xt=it;xt++;
            st.erase(it);it=xt;
            tree* g=d.ptr;
            if(d.l<=l&&r<=d.r){
                 
                if(op==d.type){
                    st.insert(data(d.l,d.r,d.type,g));
                    goto end;
                } else if(d.type){
                    tree* ptr=split(g,1,n,d.r-r);
                    res=split(g,1,n,r-l+1);
                    if(Sum(g)!=0)st.insert(data(d.l,l-1,d.type,g));
                    if(Sum(ptr)!=0)st.insert(data(r+1,d.r,d.type,ptr));
                } else {
                    tree* ptr=split(g,1,n,l-d.l);
                    res=split(g,1,n,r-l+1);
                    if(Sum(ptr)!=0)st.insert(data(d.l,l-1,d.type,ptr));
                    if(Sum(g)!=0)st.insert(data(r+1,d.r,d.type,g)); 
                }
                st.insert(data(l,r,op,res));
                goto end;
                 
            } else if(l<=d.l&&d.r<=r){
                res=merge(res,g,1,n);
            } else if(d.l<l){
                if(d.type){
                    k=d.r-l+1;
                    tree* ptr=split(g,1,n,k);
                    res=merge(res,ptr,1,n);
                    if(Sum(g)!=0)st.insert(data(d.l,l-1,d.type,g));
                } else {
                    k=l-d.l;
                    tree* ptr=split(g,1,n,k);
                    res=merge(res,g,1,n);
                    if(Sum(ptr)!=0)st.insert(data(d.l,l-1,d.type,ptr));
                }
            } else if(d.r>r){
                if(d.type){
                    k=d.r-r;
                    tree* ptr=split(g,1,n,k);
                    res=merge(res,g,1,n);
                    if(Sum(ptr)!=0)st.insert(data(r+1,d.r,d.type,ptr));
                } else {
                    k=r-d.l+1;
                    tree* ptr=split(g,1,n,k);
                    res=merge(res,ptr,1,n);
                    if(Sum(g)!=0)st.insert(data(r+1,d.r,d.type,g));
                }
            }
        }
        st.insert(data(l,r,op,res));
        end:;
         
    }
    int q;scanf("%d",&q);
    sit it=st.lower_bound(data(q,q,0,0));
    if(!it->type)printf("%d",ask(it->ptr,1,n,q-it->l+1));
    else printf("%d",ask(it->ptr,1,n,it->r-q+1));
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值