珂朵莉树
作者:互联网
这是什么?
\(\quad\)这是一种基于 set
的暴力数据结构。
什么时候用?
\(\quad\)当操作中有:推平一段区间,区间赋值,使得一段区间变得一样,保证数据随机 等字眼时。
珂朵莉树的初始化
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