[CF896C]Willem, Chtholly and Seniorious(珂朵莉树)
https://www.cnblogs.com/WAMonster/p/10181214.html
主要用于支持含有较难维护的区间操作与查询的问题,要求其中区间赋值操作(assign())是纯随机的。
注意要先split(r+1)再split(l),最好最后设一个点(n+1,n+1,0)
1 #include<set> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 typedef long long ll; 7 using namespace std; 8 9 const int N=100010; 10 int n,m,x,y,mx; ll seed; 11 struct P{ int l,r; mutable ll v; }; 12 bool operator <(const P &a,const P &b){ return a.l<b.l; } 13 set<P>S; 14 typedef set<P>::iterator sit; 15 pair<ll,int>ve[N]; 16 17 ll ksm(ll a,ll b,ll mod){ 18 ll res=1; a%=mod; 19 for (; b; a=a*a%mod,b>>=1) 20 if (b & 1) res=res*a%mod; 21 return res; 22 } 23 24 sit split(int pos){ 25 sit it=S.lower_bound((P){pos,0,0}); 26 if (it!=S.end() && it->l==pos) return it; 27 it--; int l=it->l,r=it->r; ll v=it->v; 28 S.erase(it); S.insert((P){l,pos-1,v}); 29 return S.insert((P){pos,r,v}).first; 30 } 31 32 void assign(int l,int r,ll v){ 33 sit it2=split(r+1),it1=split(l); 34 S.erase(it1,it2); S.insert((P){l,r,v}); 35 } 36 37 void add(int l,int r,ll v){ 38 sit it2=split(r+1),it1=split(l); 39 for (sit it=it1; it!=it2; it++) it->v+=v; 40 } 41 42 ll kth(int l,int r,int k){ 43 sit it2=split(r+1),it1=split(l); int tot=0; 44 for (sit it=it1; it!=it2; it++) ve[++tot]=pair<ll,int>(it->v,(it->r)-(it->l)+1); 45 sort(ve+1,ve+tot+1); 46 rep(i,1,tot){ 47 k-=ve[i].second; 48 if (k<=0) return ve[i].first; 49 } 50 return 0; 51 } 52 53 ll que(int l,int r,int x,ll y){ 54 sit it2=split(r+1),it1=split(l); 55 ll res=0; 56 for (sit it=it1; it!=it2; it++) res=(res+((it->r)-(it->l)+1)*ksm(it->v,x,y))%y; 57 return res; 58 } 59 60 int rnd(){ int ret=(int)seed; seed=(seed*7+13)%1000000007; return ret; } 61 62 int main(){ 63 freopen("CF896C.in","r",stdin); 64 freopen("CF896C.out","w",stdout); 65 cin>>n>>m>>seed>>mx; 66 rep(i,1,n) S.insert((P){i,i,rnd()%mx+1}); 67 S.insert((P){n+1,n+1,0}); 68 rep(i,1,m){ 69 int op=rnd()%4+1,l=rnd()%n+1,r=rnd()%n+1; 70 if (l>r) swap(l,r); 71 if (op==3) x=rnd()%(r-l+1)+1; else x=rnd()%mx+1; 72 if (op==4) y=rnd()%mx+1; 73 if (op==1) add(l,r,x); 74 if (op==2) assign(l,r,x); 75 if (op==3) cout<<kth(l,r,x)<<endl; 76 if (op==4) cout<<que(l,r,x,y)<<endl; 77 } 78 return 0; 79 }