其他分享
首页 > 其他分享> > 珂朵莉树

珂朵莉树

作者:互联网

这是什么?

\(\quad\)这是一种基于 set 的暴力数据结构。

什么时候用?

\(\quad\)当操作中有:推平一段区间,区间赋值,使得一段区间变得一样,保证数据随机 等字眼时。

珂朵莉树的初始化

模板题 Link

struct node{
    int l,r;
    mutable LL v;
    ndoe(int L,int R,LL V=0):l(L),r(R),v(V){}
    bool operator < (const node &o) const{
        return l<o.l;
    }
}

\(\quad\)每个节点表示区间 [l,r] 内的所有数都是 v 。需要注意的是 mutable ,意思是易变的,这里必须加上,我们将这样的节点存在 set 里面。

初始化:

set<node> s;

cin>>n>>m>>seed>>vmax;
for(int i=1;i<=n;++i){
    a[i]=(rnd()%vmax)+1;
    s.insert(node(i,i,a[i]));
}

珂朵莉树的核心操作(分裂):split

\(\quad\)split(pos) 就是指将原来含有 pos 位置的节点分为两部分:[l,pos-1][pos,r]

#define IT set<node>::iterator 
IT split(int pos){
    IT it=s.lowerbond(node(pos));
    if(it!=s.end() && it->l==pos) return it;
    --it;
    int L=it->l,R=it->r;
    LL V=it->v;
    s.erase(it);
    s,insert(node(L,pos-1,V));
    return s.insert(node(pos,R,V)).first;//这里返回了后半段的迭代器
}

珂朵莉树的核心操作(推平):assign

\(\quad\)如果只有 split 复杂度会很高,我们需要用 assign 操作减小 set 的规模

void assign(int l,int r,int val){
    IT itr=split(r+1),itl=split(l);//注意这里一定要先 split(r+1) 
    s.erase(itl,itr);
    s.insert(node(l,r,val));
}

其他操作:暴力!!!

\(\quad\)区间加:

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

\(\quad\)区间第 k 小:

LL rand(int l,int r,int k){
    vector<pair<LL,int> > V;
    V.clear();
    IT itr=split(r+1),itl=split(l);
    for(;itl!=itr;++itl) V.push_back(pair(LL,int)(itl->v,itl->r-itl->l+1));
    sort(V.begin(),V.end());
    for(vector<pair<LL,int> >::iterator it=V.begin():it!=V.end();++it){
        k-=it->second;
        if(k<=0) return it->first;
    }
    return -1LL;
}//暴力排序

\(\quad\)幂次和同理。

总代码:

#include<bits/stdc++.h>
using namespace std;

#define FOR(i,a,b) for(register int i=(a),i##i=(b);i<=i##i;++i)
#define ROF(i,a,b) for(register int i=(a),i##i=(b);i>=i##i;--i)
#define REP(u) for(register int i=head[u];i;i=e[i].nxt)
#define File_1(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
#define File_2(a) freopen(a".in","r",stdin)
typedef long long LL;

inline LL read(){
    LL ret=0,f=0;char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-') f=1;ch=getchar();}
    while(ch>='0' && ch<='9'){ret=(ret<<1)+(ret<<3)+(ch^48);ch=getchar();}
    return f?-ret:ret;
}

const int N=1e5+10,MOD7=1e9+7;
LL T,n,m,seed,vmax,a[N];

LL rd(){
    LL ret=seed;
    seed=(seed*7+13)%MOD7;
    return ret;
}

LL ksm(LL a,LL b,LL mod){
    LL res=1;
    while(b){
        if(b&1){res=res*a%mod;}
        a=a*a%mod;
        b>>=1;
    }return res;
}

namespace ODT{
    struct node{
        int l,r;
        mutable LL v;
        node(int L,int R=-1,LL V=0):l(L),r(R),v(V){}
        bool operator < (const node &t) const{
            return l<t.l;
        }
    };
    typedef set<node>::iterator iter;
    typedef vector<pair<LL,int>>::iterator Iter;
    set<node> s;

    iter split(int pos){
        iter it=s.lower_bound(node(pos));
        if(it!=s.end() && it->l==pos) return it;--it;
        int L=it->l,R=it->r;
        LL V=it->v;
        s.erase(it);
        s.insert(node(L,pos-1,V));
        return s.insert(node(pos,R,V)).first;
    }

    inline void assign_val(int l,int r,LL val){
        iter it2=split(r+1),it1=split(l);
        s.erase(it1,it2);
        s.insert(node(l,r,val));
    }

    inline void add(int l,int r,LL val){
        iter it2=split(r+1),it1=split(l);
        for(;it1!=it2;++it1) it1->v+=val;
    }

    inline LL ranks(int l,int r,int k){
        vector<pair<LL,int>> V;
        iter it2=split(r+1),it1=split(l);
        V.clear();
        for(;it1!=it2;++it1) V.push_back(pair<LL,int>(it1->v,it1->r-it1->l+1));
        sort(V.begin(),V.end());
        for(Iter it=V.begin();it!=V.end();++it){
            k-=it->second;
            if(k<=0) return it->first;
        }
    }

    inline LL sum(int l,int r,int val,int mod){
        iter it2=split(r+1),it1=split(l);LL res=0;
        for(;it1!=it2;++it1){
            res=(res+(LL)(it1->r-it1->l+1)*ksm(it1->v,(LL)val,(LL)mod)%mod)%mod;
        }
        return res;
    }
}

using namespace ODT;

inline void solve(){
    n=read();m=read();seed=read();vmax=read();
    FOR(i,1,n) {
        a[i]=(rd()%vmax)+1;
        s.insert(node(i,i,a[i]));
    }
    s.insert(node(n+1,n+1,0));
    int lines=0;
    FOR(i,1,m){
        int opt=int(rd()%4)+1,l=int(rd()%n)+1,r=int(rd()%n)+1;
        if(l>r) swap(l,r);
        int x,y;
        if(opt==3) x=int(rd()%(r-l+1))+1;
        else x=int(rd()%vmax)+1;
        if(opt==4) y=int(rd()%vmax)+1;
        if(opt==1) add(l,r,LL(x));
        else if(opt==2) assign_val(l,r,LL(x));
        else if(opt==3) printf("%lld\n",ranks(l,r,x));
        else printf("%lld\n",sum(l,r,x,y));
    }
}

标签:node,int,LL,pos,朵莉树,split,it1
来源: https://www.cnblogs.com/SPzos017/p/15895299.html