珂朵莉树(ODT老司机树)
Posted json-five
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了珂朵莉树(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; }
以上是关于珂朵莉树(ODT老司机树)的主要内容,如果未能解决你的问题,请参考以下文章
[Codeforces896C] Willem, Chtholly and Seniorious (ODT-珂朵莉树)