珂朵莉樹

zuoqingyuan111發表於2024-10-04

好文章

LUOGU
個人理解:珂朵莉樹其實就是\(set\)大法,就是暴力,可以構造特殊資料卡掉,但是在隨機資料的情況下,它是非常快的

struct ASD
{
	ll l,r;
	mutable ll val;//方便更改,指標是常量,必須加上mutable
	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;
	}
};
#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不讓用__int128
	while(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;
}

image

相關文章