1. 程式人生 > 其它 >珂朵莉樹--用set維護的暴力資料結構

珂朵莉樹--用set維護的暴力資料結構

以模板題為例:

#include<bits/stdc++.h>
#define IT set<node>::iterator
using namespace std;
typedef long long LL;
const int MOD7=1e9+7;
const int MOD9=1e9+9;
const int imax_n=1e5+7;
struct node{//珂朵莉樹的定義 
    int l,r;
    mutable LL v;
    node(int L,int R=-1,LL V=0):l(L),r(R),v(V){
		return;
	}//自定義函式 
    bool operator<(const node& o) const{//過載運算子 
        return l < o.l;
    }
};
LL pown(LL a,LL b,LL mod){//快速冪 
    LL res=1;
    LL ans=a%mod;
    while(b!=0){
        if(b&1){
            res=res*ans%mod;
        }
        ans=ans*ans%mod;
        b>>=1;
    }
    return res;
}
set<node> s;
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 V=it->v;
    s.erase(it);
    s.insert(node(L,pos-1,V));
    return s.insert(node(pos,R,V)).first;
}
void add(int l,int r,LL val){//操作一 暴力加 
    IT itr=split(r+1),itl=split(l);
    for(;itl!=itr;++itl){
        itl->v+=val;
    }
    return;
}
void assign_val(int l,int r,LL val){//操作二 分裂後修改,注意先改右邊再改左邊不然會RE 
    IT itr=split(r+1),itl=split(l);
    s.erase(itl, itr);
    s.insert(node(l,r,val));
    return;
}
LL ranks(int l, int r, int k){//操作三 排序一遍,然後暴力尋找第k小的數 
    vector<pair<LL, int> >vp;
    IT itr=split(r+1),itl=split(l);
    vp.clear();
    for(;itl!=itr;++itl){
        vp.push_back(pair<LL,int>(itl->v,itl->r-itl->l+1));
    }
    sort(vp.begin(),vp.end());
    for(vector<pair<LL,int> >::iterator it=vp.begin();it!=vp.end();++it){
        k-=it->second;
        if(k<=0){
            return it->first;
        }
    }
}
LL sum(int l,int r,int ex,int mod){//操作四 先快速冪然後全加起來 
    IT itr=split(r+1),itl=split(l);
    LL res=0;
    for(;itl!=itr;++itl){
        res=(res+(LL)(itl->r-itl->l+1)*pown(itl->v,LL(ex),LL(mod)))%mod;
    }
    return res;
}
int n,m;
LL seed,vmax;
LL a[imax_n];
LL randm(){
    LL ret=seed;
    seed=(seed*7+13)%MOD7;
    return ret;
}
int main(){
    cin>>n>>m>>seed>>vmax;
    for(int i=1;i<=n;i++){
        a[i]=(randm()%vmax)+1;
        s.insert(node(i,i,a[i]));
    }
    s.insert(node(n+1,n+1,0));
    int lines=0;
    for(int i=1;i<=m;i++){
        int op=int(randm()%4)+1;
        int l=int(randm()%n)+1;
        int r=int(randm()%n)+1;
        if(l>r){
            swap(l,r);
        }
        int x,y;
        if(op==3){
            x=int(randm()%(r-l+1))+1;
        }
        else{
            x=int(randm()%vmax)+1;
        }
        if(op==4){
            y=int(randm()%vmax)+1;
        }
        if(op==1){
            add(l,r,LL(x));
        }
        else if(op==2){
            assign_val(l,r,LL(x));
        }
        else if(op==3){
            cout<<ranks(l,r,x)<<endl;
        }
        else if(op==4){
            cout<<sum(l,r,x,y)<<endl;
        }
        else{
        	cout<<"珂朵莉是世界上最幸福的女孩!"; 
		}
    }
    return 0;
}


珂朵莉是世界上最幸福的女孩!