题解:珂朵莉树练习题组

34 篇文章 0 订阅

中国珂学院

珂朵莉树是一个可以维护区间x次方和查询的高效数据结构,原理十分暴力。

Willem, Chtholly and Seniorious

#include<bits/stdc++.h>
#define mul(a,b,c) ((a)*(b)%(c))
using namespace std;
typedef long long ll;
typedef pair<int,ll> pil;
ll pow(ll a,ll b,ll m)
{
	ll r=1;
	for(a%=m; b; a=mul(a,a,m),b>>=1)
		if(b&1)r=mul(r,a,m);
	return r;
}
struct ChthollyTree:map<int,pil>
{
	iterator split(int pos)
	{
		iterator it=lower_bound(pos);
		if(it!=end()&&it->first==pos)return it;
		--it;
		if(pos>it->second.first)return end();
		pair<int,pil> p=*it;
		erase(it);
		insert(make_pair(p.first,pil(pos-1,p.second.second)));
		return insert(make_pair(pos,p.second)).first;
	}
	void add(int l,int r,ll val)
	{
		for(iterator b=split(l),e=split(r+1); b!=e; ++b)b->second.second+=val;
	}
	void set(int l,int r,ll val)
	{
		erase(split(l),split(r+1)),insert(make_pair(l,pil(r,val)));
	}
	ll rank(int l,int r,int k)
	{
		vector<pair<ll,int> > v;
		for(iterator b=split(l),e=split(r+1); b!=e; ++b)
			v.push_back(make_pair(b->second.second,b->second.first-b->first+1));
		sort(v.begin(),v.end());
		for(int i=0; i<v.size(); ++i)
			if(k-=v[i].second,k<=0)return v[i].first;
		return -1;
	}
	ll sum(int l,int r,ll ex,ll m)
	{
		ll res=0;
		for(iterator b=split(l),e=split(r+1); b!=e; ++b)
			res=(res+mul(b->second.first-b->first+1,pow(b->second.second,ex,m),m))%m;
		return res;
	}
} t;
ll n,m,seed,vmax,M=1e9+7;
ll rnd()
{
	ll ret=seed;
	seed=(seed*7+13)%M;
	return ret;
}
int main()
{
	scanf("%lld%lld%lld%lld",&n,&m,&seed,&vmax);
	for(int i=1; i<=n; ++i)
		t.insert(make_pair(i,pil(i,rnd()%vmax+1)));
	for(int i=1; i<=m; ++i)
	{
		int op=rnd()%4+1,l=rnd()%n+1,r=rnd()%n+1;
		if(l>r)swap(l,r);
		ll x=rnd()%(op==3?r-l+1:vmax)+1;
		if(op==1)t.add(l,r,x);
		if(op==2)t.set(l,r,x);
		if(op==3)printf("%lld\n",t.rank(l,r,x));
		if(op==4)printf("%lld\n",t.sum(l,r,x,rnd()%vmax+1));
	}
}

脑洞治疗仪

#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef pair<int,ll> pil;
struct ChthollyTree:map<int,pil>
{
	iterator split(int pos)
	{
		iterator it=lower_bound(pos);
		if(it!=end()&&it->first==pos)return it;
		--it;
		if(pos>it->second.first)return end();
		pair<int,pil> p=*it;
		erase(it);
		insert(make_pair(p.first,pil(pos-1,p.second.second)));
		return insert(make_pair(pos,p.second)).first;
	}
	void set(int l,int r,ll val)
	{
		erase(split(l),split(r+1)),insert(make_pair(l,pil(r,val)));
	}
	void scure(int l,int r,int x,int y)
	{
		iterator e=split(r+1),b=split(l),it=b;
		int sum=0;
		for(; b!=e; ++b)
			if(b->second.second)
				sum+=b->second.first-b->first+1;
		erase(it,e);
		insert(make_pair(l,pil(r,0)));
		if(!sum)return;
		e=split(y+1),b=split(x),it=b;
		if(sum>=y-x+1)
		{
			erase(b,e);
			insert(make_pair(x,pil(y,1)));
			return;
		}
		for( ; b!=e; ++b)
			if(!b->second.second)
			{
				sum-=b->second.first-b->first+1;
				if(sum<0)return set(b->first,b->second.first+sum,1);
				b->second.second=1;
			}
	}
	ll MAX(int l,int r)
	{
		iterator e=split(r+1),b=split(l);
		ll res=0,now=0;
		for(; b!=e; ++b)
			if(!b->second.second)
				now+=b->second.first-b->first+1;
			else if(now)res=max(res,now),now=0;
		return max(res,now);
	}
} t;
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	t.insert(make_pair(1,pil(n,1)));
	for(int op,l,r,x,y; m--;)
	{
		scanf("%d%d%d",&op,&l,&r);
		if(op==0)t.set(l,r,0);
		else if(op==1)scanf("%d%d",&x,&y),t.scure(l,r,x,y);
		else printf("%d\n",t.MAX(l,r));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值