珂朵莉树(ODT老司机树)
题目链接https://vjudge.net/problem/CodeForces-896C
关于珂朵莉树的讲解可以参考https://blog.csdn.net/niiick/article/details/83062256
按照题意,完成加,赋值,求第K小,区间x次方和四种操作
直接上代码
#include<bits/stdc++.h>
#define ll long long
#define IT set<node>::iterator
#define I_like_Chtholly_forever 1000000007
using namespace std;
struct node
{
ll l,r;
mutable ll val;
node(ll L,ll R=-1,ll V=0): l(L), r(R), val(V) {}
bool operator < (const node& tt)const
{
return l<tt.l; //以区间左端点排序
}
};
set<node> st;
IT split(ll pos)
{
IT it=st.lower_bound(node(pos));//二分找到第一个左端点不小于pos的区间
if(it!=st.end()&&it->l==pos) return it;//pos本身就是某个区间的左端点,不用分裂
--it;//否则上一个区间才是包含pos的区间
ll l=it->l,r=it->r,val=it->val;
st.erase(it);//删除原结点
st.insert(node(l,pos-1,val));
return st.insert(node(pos,r,val)).first;//这里.first返回的是迭代器
}
void assign_val(ll l,ll r,ll val)
{
IT itr=split(r+1),itl=split(l);
st.erase(itl,itr);
st.insert(node(l,r,val));
}
#define pir pair<ll,ll>//前一个记录值,后一个记录出现次数
ll kth(ll l,ll r,ll k)
{
vector<pir> vec;
IT itr=split(r+1),itl=split(l);
for(; itl!=itr; ++itl)
vec.push_back( pir(itl->val,itl->r-itl->l+1) );
sort(vec.begin(),vec.end());//全部存下来排序就好
for(vector<pir>::iterator it=vec.begin(); it!=vec.end(); ++it)
{
k-=it->second;
if(k<=0) return it->first;
}
return -1;
}
void add(ll l,ll r,ll val)
{
IT itr=split(r+1),itl=split(l);
for(; itl!=itr; ++itl)
{
itl->val+=val;
}
}
ll quick_pow(ll a, ll b, ll mod)
{
ll res = 1;
ll ans = a % mod;
while (b)
{
if (b&1)
res = res * ans % mod;
ans = ans * ans % mod;
b>>=1;
}
return res;
}
ll sum(ll l,ll r,ll en,ll mod)
{
IT itr=split(r+1),itl=split(l);
ll res=0;
for(; itl!=itr; ++itl)
{
res = (res + (itl->r-itl->l +1) * quick_pow(itl->val,en,mod))%mod;
}
return res;
}
ll n,m,vmax,seed;
ll rnd()
{
ll ret = seed;
seed = (seed * 7 + 13) % I_like_Chtholly_forever;
return ret;
}
ll a[100005];
int main()
{
cin>>n>>m>>seed>>vmax;
for (int i = 1; i<= n; i++)
{
a[i] = (rnd() % vmax) + 1;
st.insert(node(i,i,a[i]));
}
ll op,l,r,x,y;
for (int i=1; i<=m; i++ )
{
op = (rnd() % 4) + 1;
l = (rnd() % n) + 1;
r = (rnd() % n) + 1;
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);
else if (op == 2)
assign_val(l, r, x);
else if (op == 3)
cout<<kth(l,r,x)<<endl;
else
cout<<sum(l,r,x,y)<<endl;
}
return 0;
}

浙公网安备 33010602011771号