P6638 「JYLOI Round 1」常规 题解

题目传送门

前置知识

可持久化线段树 | 前缀和 & 差分

解法

进行差分,区间查询转化成前缀和相减。

先将 {a} 升序排序。

设当前询问的区间为 [1,r],在 {a} 中找到一个最大的 pos 使得 aposr,则 [1,r] 中所做常规的次数为 i=1posraik

考虑拆开向下取整,有 i=1posraik=i=1posrai(rai)modkk=1k×i=1posrai(rai)modk=1k×(r×posi=1posaii=1pos(rai)modk)

难点在于怎么求 i=1pos(rai)modk。考虑按照取模运算的性质拆开并适当补上 +k,有 (rai)modk=rmodkaimodk+[rmodk<aimodk]×k

aimodk 为权值建立一棵主席树然后主席树上查询 [1,pos] 内满足 aimodk(rmodk,k) 即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
ll a[100010],sum1[100010],sum2[100010];
struct PDS_SMT
{
	ll root[100010],rt_sum=0;
	struct SegmentTree
	{
		ll ls,rs,sum;
	}tree[100010<<5];
	#define lson(rt) tree[rt].ls
	#define rson(rt) tree[rt].rs
	ll build_rt()
	{
		rt_sum++;
		return rt_sum;
	}
	void update(ll pre,ll &rt,ll l,ll r,ll pos)
	{
		rt=build_rt();
		tree[rt]=tree[pre];
		tree[rt].sum++;
		if(l==r)
		{
			return;
		}
		ll mid=(l+r)/2;
		if(pos<=mid)
		{
			update(lson(pre),lson(rt),l,mid,pos);
		}
		else
		{
			update(rson(pre),rson(rt),mid+1,r,pos);
		}
	}
	ll query(ll rt,ll l,ll r,ll x,ll y)
	{
		if(x<=l&&r<=y)
		{
			return tree[rt].sum;
		}
		ll mid=(l+r)/2,ans=0;
		if(x<=mid)
		{
			ans+=query(lson(rt),l,mid,x,y);
		}
		if(y>mid)
		{
			ans+=query(rson(rt),mid+1,r,x,y);
		}
		return ans;
	}
}T;
ll ask(ll r,ll n,ll k)
{
	ll ans=0,pos=upper_bound(a+1,a+1+n,r)-a-1;
	ans+=r*pos;
	ans-=sum1[pos];
	ans-=(r%k)*pos;
	ans+=sum2[pos];
	ans-=T.query(T.root[pos],0,k-1,r%k+1,k-1)*k;
	return ans/k;
}
int main()
{
	ll type,n,m,k,mod,l,r,ans=0,i;
	cin>>type>>n>>m>>k;
	if(type==1)
	{
		cin>>mod;
	}
	for(i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	sort(a+1,a+1+n);
	for(i=1;i<=n;i++)
	{
		sum1[i]=sum1[i-1]+a[i];
		sum2[i]=sum2[i-1]+a[i]%k;
		T.update(T.root[i-1],T.root[i],0,k-1,a[i]%k);
	}
	cin>>l>>r;
	ans=ask(r,n,k)-ask(l-1,n,k);
	cout<<ans<<endl;
	for(i=2;i<=m;i++)
	{
		cin>>l>>r;
		if(type==1)
		{
			l=(l+ans-1)%mod+1;
			r=(r+ans-1)%mod+1;
			if(l>r)
			{
				swap(l,r);
			}
		}
		ans=ask(r,n,k)-ask(l-1,n,k);
		cout<<ans<<endl;
	}
	return 0;
}
posted @   hzoi_Shadow  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
扩大
缩小
点击右上角即可分享
微信分享提示