首页 > 其他 > 详细

珂朵莉树(学习笔记)

时间:2019-08-11 23:02:21      阅读:134      评论:0      收藏:0      [点我收藏+]

推荐一篇博客,珂朵莉树本来就是一种暴力数据结构,思想很简单,实现也比线段树简单一点.学习珂朵莉树其实只要学好了STL的\(set\)的就行了.

因为珂朵莉树实在是没有什么要讲的东西,然后该讲的上面那篇博客也讲得差不多了.这里我就只讲几个珂朵莉树能够实现的几个基本操作.

先放上几套模板题.

CF896C Willem, Chtholly and Seniorious珂朵莉树的入坑题???

[SCOI2010]序列操作

语文1(chin1)- 理理思维

CF915E Physical Education Lessons

[SHOI2015]脑洞治疗仪

分裂操作(前置操作,实现其他操作的基础)

inline IT split(int pos){
    IT it=s.lower_bound(node(pos));
    if(it!=s.end()&&it->l==pos)return it;
    --it;
    int l=it->l,r=it->r;ll val=it->val;
    s.erase(it);
    s.insert(node(l,pos-1,val));
    return s.insert(node(pos,r,val)).first;
}

操作一:区间赋值(这是珂朵莉树的必备操作,如果没有这个操作珂朵莉树可能真的就是\(n^2\)暴力了)

inline void assign(int l,int r,int val){//将[l,r]赋值为val
    IT itr=split(r+1),itl=split(l);
    s.erase(itl,itr);
    s.insert(node(l,r,val));
}

操作二:区间修改,将\([l,r]\)中每个值加上val

inline void add(int l,int r,int val){
    IT itr=split(r+1),itl=split(l);
    for(;itl!=itr;++itl)itl->val+=val;
    return;
}

操作三:区间k小值

inline ll kth(int l,int r,int k){
    vector<pair<int,int> >q;
    IT itr=split(r+1),itl=split(l);
    for(;itl!=itr;++itl)
        q.push_back(pair<int,int>(itl->val,itl->r-itl->l+1));
    sort(q.begin(),q.end());
    for(vector<pair<int,int> >::iterator it=q.begin();it!=q.end();++it){
        k-=it->second;
        if(k<=0)return it->first;
    }
}

操作四:区间\([l,r]\)总共有多少个va

inline int ask1(int l,int r,int val){
    int ans=0;
    IT itr=split(r+1),itl=split(l);
    for(;itl!=itr;++itl)
        if(itl->val==val)ans+=(itl->r-itl->l+1);
    return ans;
}

操作五:区间\([l,r]\)中最多有多少个连续的val

inline int ask2(int l,int r,int val){
    int ans=0,cnt=0;
    IT itr=split(r+1),itl=split(l);
    for(;itl!=itr;++itl){
        if(itl->val!=val)ans=max(ans,cnt),cnt=0;
        else cnt+=itl->r-itl->l+1;
    }
    return max(ans,cnt);
}

操作六:将区间[l,r]从小到大排序,这个与求区间k小是不同的,因为区间K小只需要将区间的数(拎出来)排序,然后求第k个,不需要更改原区间的数的顺序.(代码中保证了区间中的数在1到26之间,所以可以开桶)

void get_sort(int l,int r){
    memset(sum,0,sizeof(sum));
    IT itr=split(r+1),itl=split(l),it=itl;
    for(;it!=itr;++it)sum[it->val]+=it->r-it->l+1;
    s.erase(itl,itr);
    for(int i=1;i<=26;++i)
        if(sum[i]){
            s.insert(node(l,l+sum[i]-1,i));
            l+=sum[i];
        }
}

其他操作大家见仁见智就好了,反正怎么来都是暴力.优雅的暴力也是暴力.

珂朵莉树(学习笔记)

原文:https://www.cnblogs.com/PPXppx/p/11336454.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!