【CodeForces-896C】— Willem, Chtholly and Seniorious(ODT老驱动树)
真是个好暴力 的东西
但是只有在随机数据下才有用(当然如果随机数据都把你卡了又有什么办法,就好像生成了一条链一样)
而且只能在有区间覆盖操作的里面
因为考虑到覆盖之后整个区间都是同样的数了
那我们可以把这一个区间压成一个点
最后我们就得到了很多个点
修改询问的时候都直接整体修改就可以了
然后就像暴力一样遍历整个区间就完了
注意随时取膜,否则到处爆
#include<bits/stdc++.h>
using namespace std;
#define gc getchar
#define ll long long
#define int long long
#define IT set<node>::iterator
#define pi pair<ll,int>
#define mp(x,y) make_pair(x,y)
inline int read(){
int res=0,f=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while((isdigit(ch)))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res;
}
#undef gc
ll seed,mxv;
inline ll rnd(){
int res=seed;
seed=(seed*7+13)%1000000007;
return res;
}
const int N=100005;
int n,m;
ll a[N];
struct node{
int l,r;
mutable ll val;
node(int L,int R=-1,ll v=0):l(L),r(R),val(v){}
bool operator < (const node &a)const {return l<a.l;}
};
set<node>st;
inline ll ksm(ll a,ll b,ll mod){
int res=1;a%=mod;
for(;b;b>>=1,a=a*a%mod){
if(b&1)res=res*a%mod;
}
return res;
}
inline IT split(int pos){
IT it=st.lower_bound(node(pos));
if(it!=st.end()&&it->l==pos)return it;
it--;
int l=it->l,r=it->r;
ll val=it->val;
st.erase(it);
st.insert(node(l,pos-1,val));
return st.insert(node(pos,r,val)).first;
}
inline void assign(int l,int r,ll val){
IT itr=split(r+1),itl=split(l);
st.erase(itl,itr);
st.insert(node(l,r,val));
}
inline void add(int l,int r,int val){
IT itr=split(r+1),itl=split(l);
for(;itl!=itr;itl++)itl->val+=val;
}
inline ll kth(int l,int r,int k){
vector<pi>vec;
IT itr=split(r+1),itl=split(l);
for(;itl!=itr;itl++)
vec.push_back(mp(itl->val,itl->r-itl->l+1));
sort(vec.begin(),vec.end());
for(vector<pi>::iterator it=vec.begin();it!=vec.end();it++){
k-=it->second;
if(k<=0)return it->first;
}
return -1;
}
ll sum(int l,int r,ll x,ll y){
ll res=0;
IT itr=split(r+1),itl=split(l);
for(;itl!=itr;++itl)
res+=(ksm(itl->val,x,y)*((itl->r-itl->l+1)%y))%y,res%=y;
return res;
}
signed main(){
n=read();m=read();
seed=read();mxv=read();
for(int i=1;i<=n;++i){
a[i]=(rnd()%mxv)+1;
st.insert(node(i,i,a[i]));
}
for(int i=1;i<=m;++i){
int op=(rnd()%4)+1;
int l=(rnd()%n)+1,r=(rnd()%n)+1;
ll x,y;
if(l>r) swap(l,r);
if(op==3) x=(rnd()%(r-l+1))+1;
else x=(rnd()%mxv)+1;
if(op==4) y=(rnd()%mxv)+1;
if(op==1) add(l,r,x);
else if(op==2) assign(l,r,x);
else if(op==3) printf("%lld\n",kth(l,r,x));
else if(op==4) printf("%lld\n",sum(l,r,x,y));
}
return 0;
}