noip模拟题 ----飞

本题的空间限制是32MB

可以发现实际上就是要求有多少对线段产生了相交

又因为y轴上是升序,所以就是求产生的序列中,有多少个逆序对

可以发现因为数据生成的方法是有迹可循的,我们可以将值域分块

每a的长度就是一个块,可以通过一个块的贡献统计其他块的贡献,就减少了空间和时间复杂度

用树状数组来维护这个东西

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define RG register
using namespace std;
int shu,n,a,mod,maxa,piece,pos,pd[100005];
long long all,now,another;
long long ans,tree[100005];
inline void modify(int x)
{
	x++;
	for(RG int i=x;i<=1e5;i+=(i&-i))
	tree[i]++;
}
inline long long query(int x)
{
	x++;
	RG long long ans=0;
	for(RG int i=x;i>=1;i-=(i&-i))
	ans+=tree[i];
	return ans;
}
int get(int x)
{
	return x/a+1;
}
inline int moc(int x)
{
	if(x>=mod) return x-mod;
	return x;
}
int main()
{
	freopen("fly.in","r",stdin);
	freopen("fly.out","w",stdout);
	cin>>n>>shu>>a>>mod;
	int pre=shu;
	modify(shu%a);
	int pos=get(shu)-1,remain=1,tot=1;
	for(int i=2;i<=n;i++)
	{
		shu+=a;
		if(shu>=mod)
		{
			shu-=mod;
			tot++;
			modify(shu);
			remain=query(shu);
		}
		int now=get(shu);
		int temp=tot*(now-1)+remain;
		if(shu%a>=pre%a) temp-=min(now,pos);
		else temp-=min(now-1,pos);
		ans+=i-temp;
	}
	cout<<ans;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值