好文章
个人理解:珂朵莉树其实就是\(set\)大法,就是暴力,可以构造特殊数据卡掉,但是在随机数据的情况下,它是非常快的
struct ASD
{ll l,r;mutable ll val;//方便更改,指针是常量,必须加上mutablebool operator < (const ASD& A)const{return l<A.l;}ASD(ll a,ll b,ll c){l=a;r=b;val=c;}ASD(ll a){l=a;}
};
#define sit set<ASD>::iterator//懒人
分裂操作,将一个区间中的一个位置分裂成\([l,pos],[pos+1,r]\),是核心步骤,以后都是围绕他进行的
set<ASD> s;sit split(ll pos){sit it=s.lower_bound(ASD(pos));if(it!=s.end()&&(*it).l==pos)return it;it--;ll l=(*it).l,r=(*it).r,val=(*it).val;s.erase(it);s.insert(ASD(l,pos-1,val));//注意边界啊,以后要用到return s.insert(ASD(pos,r,val)).first;//first返回迭代器,second返回值}
区间推平,很暴力,一定要先找\(r+1\),再找&l&,否则位置会改变,\(RE\)
void assign(ll l,ll r,ll val){sit it2=split(r+1),it1=split(l);//删除区间[l,r+1)中所有的节点,注意左闭右开s.erase(it1,it2);s.insert(ASD(l,r,val));}
同理,区间加
void add(ll l,ll r,ll val){sit it2=split(r+1),it1=split(l);for(sit it=it1;it!=it2;it++){(*it).val+=val;}}
查找第\(k\)小
ll kth(ll l,ll r,ll k){sit it2=split(r+1),it1=split(l);vector <pair<ll,ll>> a;a.clear();for(sit it=it1;it!=it2;it++){a.push_back({(*it).val,(*it).r-(*it).l+1});}sort(a.begin(),a.end());//排个序就行了,真暴力for(ull i=0;i<a.size();i++){k-=a[i].second;if(k<=0)return a[i].first;}// return 0;}
简单封一封
#define sit set<ASD>::iterator
struct ASD
{ll l,r;mutable ll val;bool operator < (const ASD& A)const{return l<A.l;}ASD(ll a,ll b,ll c){l=a;r=b;val=c;}ASD(ll a){l=a;}
};
struct ODT
{set<ASD> s;sit split(ll pos){sit it=s.lower_bound(ASD(pos));if(it!=s.end()&&(*it).l==pos)return it;it--;ll l=(*it).l,r=(*it).r,val=(*it).val;s.erase(it);s.insert(ASD(l,pos-1,val));return s.insert(ASD(pos,r,val)).first;}void assign(ll l,ll r,ll val){sit it2=split(r+1),it1=split(l);s.erase(it1,it2);s.insert(ASD(l,r,val));} void add(ll l,ll r,ll val){sit it2=split(r+1),it1=split(l);for(sit it=it1;it!=it2;it++){(*it).val+=val;}}ll kth(ll l,ll r,ll k){sit it2=split(r+1),it1=split(l);vector <pair<ll,ll>> a;a.clear();for(sit it=it1;it!=it2;it++){a.push_back({(*it).val,(*it).r-(*it).l+1});}sort(a.begin(),a.end());for(ull i=0;i<a.size();i++){k-=a[i].second;if(k<=0)return a[i].first;}// return 0;}ll cx(ll l ,ll r,ll x,ll mod){sit it2=split(r+1),it1=split(l);ll ans=0;for(sit it=it1;it!=it2;it++){ans=(ans+((*it).r-(*it).l+1)*qpow((*it).val,x,mod)%mod)%mod;}return ans;}
}odt;
例题
[模板CF896C]
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define ull unsigned long long
#define lid (rt<<1)
#define rid (rt<<1|1)
// #define endl '\n'
//#define int long long
#define pb push_back
#define pii pair<int,int>using namespace std;
ll qpow(ll a,ll b,ll mod)
{ll ans=1;a%=mod;//一定要有,CF不让用__int128while(b){if(b&1)ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans;
}
#define sit set<ASD>::iterator
struct ASD
{ll l,r;mutable ll val;bool operator < (const ASD& A)const{return l<A.l;}ASD(ll a,ll b,ll c){l=a;r=b;val=c;}ASD(ll a){l=a;}
};
struct ODT
{set<ASD> s;sit split(ll pos){sit it=s.lower_bound(ASD(pos));if(it!=s.end()&&(*it).l==pos)return it;it--;ll l=(*it).l,r=(*it).r,val=(*it).val;s.erase(it);s.insert(ASD(l,pos-1,val));return s.insert(ASD(pos,r,val)).first;}void assign(ll l,ll r,ll val){sit it2=split(r+1),it1=split(l);s.erase(it1,it2);s.insert(ASD(l,r,val));} void add(ll l,ll r,ll val){sit it2=split(r+1),it1=split(l);for(sit it=it1;it!=it2;it++){(*it).val+=val;}}ll kth(ll l,ll r,ll k){sit it2=split(r+1),it1=split(l);vector <pair<ll,ll>> a;a.clear();for(sit it=it1;it!=it2;it++){a.push_back({(*it).val,(*it).r-(*it).l+1});}sort(a.begin(),a.end());for(ull i=0;i<a.size();i++){k-=a[i].second;if(k<=0)return a[i].first;}// return 0;}ll cx(ll l ,ll r,ll x,ll mod){sit it2=split(r+1),it1=split(l);ll ans=0;for(sit it=it1;it!=it2;it++){ans=(ans+((*it).r-(*it).l+1)*qpow((*it).val,x,mod)%mod)%mod;}return ans;}
}odt;
const int N = 1e5+5;
ll n,m,seed,vmax,a[N];
ll rnd()
{ll ret = seed;seed = (seed * 7 + 13)%1000000007;return ret;
}int main ()
{speed();// freopen("in.in","r",stdin);// freopen("out.out","w",stdout);cin>>n>>m>>seed>>vmax;// cout<<n<<endl;for(int i=1;i<=n;i++){a[i]=(rnd()%vmax)+1;odt.s.insert(ASD(i,i,a[i]));}// cout<<"******"<<endl;ll op,l,r,x,y;for(int i=1;i<=m;i++){// cout<<i<<endl;op=(rnd()%4)+1;// cout<<op<<endl;l=(rnd()%n)+1;r=(rnd()%n)+1;if(l>r)swap(l,r);if(op==3){x=rnd()%(r-l+1)+1;cout<<odt.kth(l,r,x)<<endl;}else{x=rnd()%vmax+1;}if(op==1){// cout<<i<<endl;odt.add(l,r,x);}if(op==2)odt.assign(l,r,x);if(op==4){y=rnd()%vmax+1;cout<<odt.cx(l,r,x,y)<<endl;}// cout<<"*******"<<endl;}return 0;
}