用set搞的比较神奇的树吧,玄学时间复杂度,代码简洁好写,无聊学了用来水题再好不过了 ~ ~ ~
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#define X first
#define Y second
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define pb push_back
#define mk make_pair
#define IT set<node>::iterator
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;
int n,m;
LL seed,vmax;
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));
if(it!=s.end()&&it->l==pos) return it;
--it;
int L=it->l,R=it->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 itr=split(r+1),itl=split(l);
s.erase(itl,itr);
s.insert(node(l,r,val));
}
void add(int l,int r,LL val)//区间加
{
IT itr=split(r+1),itl=split(l);
for(;itl!=itr;++itl)
itl->v+=val;
}
LL ran(int l,int r,int k)//区间第k小
{
vector<pair<LL,int> >v;
IT itr=split(r+1),itl=split(l);
for(;itl!=itr;itl++)
v.pb({itl->v,itl->r-itl->l+1});
sort(v.begin(),v.end());
for(vector<pair<LL,int> >::iterator it=v.begin();it!=v.end();it++)
{
k-=it->second;
if(k<=0) return it->first;
}
}
LL qmi(LL a,LL b,LL mod)
{
LL ans=1;
a%=mod;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
LL sum(int l,int r,int ex,int mod)//区间幂次和
{
IT itr=split(r+1),itl=split(l);
LL ans=0;
for(;itl!=itr;itl++)
ans=(ans+(LL)((itl->r-itl->l+1)%mod)*qmi(itl->v,LL(ex),LL(mod))%mod)%mod;
return ans%mod;
}
LL rad()
{
LL ret=seed;
seed=(seed*7+13)%1000000007;
return ret;
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
cin>>n>>m>>seed>>vmax;
for(int i=1;i<=n;i++)
{
LL x=(rad()%vmax)+1;
s.insert(node(i,i,x));
}
s.insert(node(n+1,n+1,0));
for(int i=1;i<=m;i++)
{
int op=(rad()%4)+1;
int l=(rad()%n)+1;
int r=(rad()%n)+1;
if(l>r) swap(l,r);
int x,y;
if(op==3) x=(rad()%(r-l+1))+1;
else x=(rad()%vmax)+1;
if(op==4) y=(rad()%vmax)+1;
if(op==1) add(l,r,1ll*x);
else if(op==2) assign_val(l,r,1ll*x);
else if(op==3) printf("%lld\n",ran(l,r,1ll*x));
else printf("%lld\n",sum(l,r,x,y));
}
return 0;
}
/*
*/