ODT(珂朵莉树)

洛谷题解上说珂朵莉是最可爱的女孩,XX不服,于是发表了这篇ODT模板

原题 CF896C

#include <cstdio>
#include <set>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <map>
#define M mutable 
#define P pair<ll,ll>
#define VIT vector<P>::iterator
#define IT set<node>::iterator //宏定义set的迭代器 
#define debug() puts("我喜欢李靖妍")
using namespace std;
typedef long long ll;
const ll mod=1e9+7;

ll n,m,seed,vmax;
struct node 
{
	ll l,r;
	M ll val; //不写mutable ? RE伺候你
	node(ll L,ll R=-1,ll V=0):l(L),r(R),val(V){}
	bool operator < (const node& ljy) const
	{
		return l<ljy.l;//就查左区间
	}
};
set<node> s;

bool cmp(P x,P y)
{
	return x.first<y.first;
}

IT split(int now)
{
	IT it=s.lower_bound(node(now));//set里也有lowerbound
	if(it!=s.end()&&it->l==now)
	{
		return it;
	}
	it--;
	int l=it->l,r=it->r;
	ll V=it->val;
	s.erase(it);
	s.insert(node(l,now-1,V));
	return s.insert(node(now,r,V)).first;
}

void add(int l,int r,int v)
{
	IT lef=split(l),ri=split(r+1);
	for(;lef!=ri;lef++)
	lef->val+=v;//+=
}

void change(int l,int r,int v)
{
	IT lef=split(l),ri=split(r+1);
	s.erase(lef,ri);
	s.insert(node(l,r,v));
}

ll _sort(ll l,ll r,ll k)
{
	vector<P> v;
	v.clear();
	IT lef=split(l),ri=split(r+1);
	for(;lef!=ri;lef++)
	{
		ll lle=lef->l,rr=lef->r,val=lef->val;
		v.push_back(P(val,rr-lle+1));
	}
	sort(v.begin(),v.end(),cmp);
	for(VIT it=v.begin();it!=v.end();it++)
	{
		k-=it->second;
		if(k<=0)
		return it->first;
	}
	return -1;
}

ll ksm(ll x,ll y,ll Mod)
{
	x=x%Mod;
	ll ans=1;
	while(y)
	{
		if(y&1)
		ans=ans*x%Mod;
		x=x*x%Mod;
		y>>=1;
	}
	return ans;
}

ll cal(int l,int r,int x,int y)
{
	IT lef=split(l),ri=split(r+1);
	ll ans=0;
	for(;lef!=ri;lef++)
	{
		ll lle=lef->l,rr=lef->r,val=lef->val;
		ans=(ans+(rr-lle+1)*ksm(val,x,y)%y)%y;
	}
	return ans;
}

ll rnd()
{
	ll ret=seed;
	seed=(seed*7+13)%mod;
	return ret;
}

int main()
{
	ll op,l,r,x,y;
	scanf("%lld%lld%lld%lld",&n,&m,&seed,&vmax);
	for(ll i=1,tmp;i<=n;i++)
	{
		tmp=rnd()%vmax+1;
		s.insert((node){i,i,tmp});
	}
	for(ll 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);
			continue;
		}
		if(op==2)
		{
			change(l,r,x);
			continue;
		}
		if(op==3)
		{
			printf("%lld\n",_sort(l,r,x));
			continue;
		}
		if(op==4)
		{
			printf("%lld\n",cal(l,r,x,y));
			continue;
		}
	}
	return 0;
}

  需要注意的几点

  1.OI禁止使用auto 所以宏定义I

  2.split时应该先做右区间,再做左区间

  3.LJY 才是最可爱的女孩

——2021届解轩

猜你喜欢

转载自www.cnblogs.com/btjzoi/p/11722468.html