1. 程式人生 > >noip模擬題 ----飛

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;
}