#珂朵莉树#CF896C Willem, Chtholly and Seniorious

题目

支持区间加,区间推平,询问区间第\(k\)小,
以及询问区间\(\sum{a_i^x}\pmod y\),数据随机


分析

由于数据随机,那么区间推平的概率为\(\frac{1}{4}\)
考虑用珂朵莉树实现,用\(STL::set\)装下相同元素段,
对于取出一段区间,分离左右端点,直接修改即可


代码

#include <cstdio>
#include <cctype>
#include <set>
#include <algorithm>
#define rr register
using namespace std;
typedef long long lll; 
struct rec{
	int l,r; mutable lll w;
	inline bool operator <(const rec &t)const{
	    return l<t.l;
	}
};
struct Two{
    lll w; int len;
    inline bool operator <(const Two &t)const{
	    return w<t.w;
	}
}b[100011]; 
typedef set<rec>::iterator ir; ir it0,it1,it;
set<rec>K; int n,m,seed,mx,mod;
inline void print(lll ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline signed Get(){
	rr int ans=seed;
	seed=(7ll*seed+13)%1000000007;
	return ans;
}
inline lll ksm(lll x,lll y,lll p){
	rr lll ans=1;
	for (;y;y>>=1,x=x*x%p)
	    if (y&1) ans=ans*x%p;
	return ans;
}
inline ir Split(int x){
	it=K.lower_bound((rec){x,0,0});
	if (it!=K.end()&&it->l==x) return it;
	rr rec t=*(--it); K.erase(it);
	K.insert((rec){t.l,x-1,t.w});
	return K.insert((rec){x,t.r,t.w}).first;
}
inline void Assign(int l,int r,int w){
	it1=Split(r+1),it0=Split(l);
	K.erase(it0,it1);
	K.insert((rec){l,r,w});
}
signed main(){
	scanf("%d%d%d%d",&n,&m,&seed,&mx);
	for (rr int i=1;i<=n;++i)
		K.insert((rec){i,i,Get()%mx+1});
	K.insert((rec){n+1,n+1,0});
	for (rr int i=1;i<=m;++i){
		rr int opt=Get()%4+1,l=Get()%n+1,r=Get()%n+1;
		if (l>r) l^=r,r^=l,l^=r;
		switch (opt){
			case 1:{
				rr int x=Get()%mx+1;
				it1=Split(r+1),it0=Split(l);
				for (;it0!=it1;++it0) it0->w+=x;
				break;
			}
			case 2:{
				rr int x=Get()%mx+1;
				Assign(l,r,x);
				break;
			}
			case 3:{
				rr int kth=Get()%(r-l+1)+1,tot=0;
				it1=Split(r+1),it0=Split(l);
				for (;it0!=it1;++it0){
					rr rec t=*it0;
					b[++tot]=(Two){t.w,t.r-t.l+1};
				}
				sort(b+1,b+1+tot);
				for (rr int i=1;i<=tot;++i){
					kth-=b[i].len;
					if (kth<=0) {print(b[i].w),putchar(10); break;}
				}
				break;
			}
			case 4:{
				rr int y=Get()%mx+1,mod=Get()%mx+1; rr lll ans=0;
				it1=Split(r+1),it0=Split(l);
				for (;it0!=it1;++it0){
					rr rec t=*it0;
					ans=(ans+ksm(t.w,y,mod)*(t.r-t.l+1)%mod)%mod;
				}
				print(ans),putchar(10);
				break;
			}
		}
	}
	return 0;
} 
posted @ 2021-08-24 11:02  lemondinosaur  阅读(46)  评论(0编辑  收藏  举报