珂朵莉树
Posted emcikem
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了珂朵莉树相关的知识,希望对你有一定的参考价值。
- 将一段区间的值全变成c
- 区间加
- 区间第k小的数
区间幂次和
传送门模板
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <algorithm>
#define IT set<node>::iterator
using namespace std;
const int maxn = 1e5+5;
const int inf = 0x3f3f3f3f;
const int mod7 = 1e9+7;
typedef long long ll;
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
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& o)const{//重载运算符,以左端点升序
return l < o.l;
}
};
set<node>s;
IT split(int pos){
IT it = s.lower_bound(node(pos));//找到首个不小于pos的set
if(it!=s.end()&&it->l==pos)return it;
it--;
int L = it->l,R = it->r;//要分裂的区间[l,r]
ll V = it->v;
s.erase(it);//删除原集合
s.insert(node(L,pos-1,V));//构成前半段的新结合
return s.insert(node(pos,R,V)).first;//构成后半段的新集合,并返回地址
}
void assign_val(int l,int r,ll val){//区间推平
IT itl = split(l),itr = split(r+1);//求出要被摊平区间的收尾地址
s.erase(itl,itr);
s.insert(node(l,r,val));
}
void add(int l,int r,ll val){//区间加
IT itl = split(l),itr = split(r+1);
for(;itl!=itr;itl++){
itl->v+=val;
}
}
ll Rank(int l,int r,int k){//区间第k小
vector<pair<ll,int> > vp;
IT itl = split(l),itr = split(r+1);
vp.clear();
for(;itr!=itl;itl++){
vp.push_back(pair<ll,int >(itl->v,itl->r-itl->l+1));
}
sort(vp.begin(),vp.end());
vector<pair<ll,int > >::iterator it;
for(it=vp.begin();it!=vp.end();it++){
k -= it->second;
if(k<=0)return it->first;
}
return 0;
}
ll pow(ll a,ll b,ll p){
ll ans = 1;
a = a%p;
while(b){
if(b&1)ans=ans*a%p;
b>>=1;
a = a*a%p;
}
return ans;
}
ll sum(int l,int r,int ex,int p){
IT itl = split(l),itr = split(r+1);
ll ans = 0;
for(;itr!=itl;itl++){
ans = (ans + (ll)(itl->r - itl->l + 1) * pow(itl->v,ll(ex), ll(p))) % p;
}
return ans;
}
ll seed,vmax;
ll a[maxn];
ll rnd(){
ll ret = seed;
seed = (seed*7+13)%mod7;
return ret;
}
int main(){
int n = read(),m = read();
cin>>seed>>vmax;
for(int i=1;i<=n;i++){
a[i] = rnd()%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(rnd()%4)+1;
int l = int(rnd()%n)+1;
int r = int(rnd()%n)+1;
if(l>r)swap(l,r);
int x,y;
if(op==3)x=(rnd()%(r-l+1))+1;
else x=(rnd()%vmax)+1;
if(op==4)y=(rnd()%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<<Rank(l,r,x)<<endl;
else cout<<sum(l,r,x,y)<<endl;
}
return 0;
}
以上是关于珂朵莉树的主要内容,如果未能解决你的问题,请参考以下文章
CF896C Willem, Chtholly and Seniorious 珂朵莉树