题目描述
给出\(n\)个数,支持区间加,区间覆盖,区间第\(k\)小,区间的\(x\)次幂和.数据随机
解题思路
学ODT之前,第四个操作我是维护不来的.
第一次写ODT,ODT在数据随机有区间覆盖操作的情况下有优秀的复杂度.
关键就是用一棵平衡树维护覆盖的区间,其他就是暴力......
#include<cstdio>
#include<set>
#include<algorithm>
#define IT set<jz>::iterator
#define LL long long
using namespace std;
const int maxn=100005,tt=1e9+7;
int sd,n,m,a[maxn],vmax,top;
struct jz{
int l,r;mutable LL v;
jz(int l=0,int r=0,LL v=0):l(l),r(r),v(v){}
bool operator<(const jz &b)const{return l<b.l;}
}b[maxn];
set<jz> st;
int rnd(){int num=sd;sd=((LL)sd*7+13)%tt;return num;}
IT split(int x){
IT it=st.lower_bound(jz(x,0,0));
if (it!=st.end()&&it->l==x) return it;it--;
int l=it->l,r=it->r;LL v=it->v;st.erase(it);
st.insert(jz(l,x-1,v));return st.insert(jz(x,r,v)).first;
}
void assign(int l,int r,int v){
IT itr=split(r+1),itl=split(l);
st.erase(itl,itr);st.insert(jz(l,r,v));
}
void add(int l,int r,int x){
IT itr=split(r+1),itl=split(l);
for (IT i=itl;i!=itr;i++) i->v+=x;
}
bool cmp(jz x,jz y){return x.v<y.v;}
LL kth(int l,int r,int k){
IT itr=split(r+1),itl=split(l);top=0;
for (IT i=itl;i!=itr;i++) b[++top]=jz(i->l,i->r,i->v);
sort(b+1,b+1+top,cmp);
for (int i=1;i<=top;i++) if (k<=b[i].r-b[i].l+1) return b[i].v;else k-=b[i].r-b[i].l+1;
}
int qsm(int w,int b,int tt){int num=1;while(b){if (b&1) num=(LL)num*w%tt;w=(LL)w*w%tt;b>>=1;}return num;}
int work(int l,int r,int x,int y){
IT itr=split(r+1),itl=split(l);int num=0;
for (IT i=itl;i!=itr;i++) num=(num+(LL)qsm(i->v%y,x,y)*(i->r-i->l+1)%y)%y;
return num;
}
int main(){
freopen("exam.in","r",stdin);
freopen("exam.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&sd,&vmax);
for (int i=1;i<=n;i++) a[i]=rnd()%vmax+1,st.insert(jz(i,i,a[i]));
for (int i=1;i<=m;i++){
int op=rnd()%4+1,l=rnd()%n+1,r=rnd()%n+1,x,y;
if (l>r) swap(l,r);
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,x);
if (op==2) assign(l,r,x);
if (op==3) printf("%lld\n",kth(l,r,x));
if (op==4) printf("%d\n",work(l,r,x,y));
}
return 0;
}