1820BThe BOSS Can Count Pairs[分块]

发布时间 2023-09-20 21:08:19作者: qbning

Problem - B - Codeforces

题意是给n个a和b,1<=a,b<=n,问有多少ai*aj==bi+bj,i<j ,2e5的数据规模


看一眼数据规模,a,b都是小于等于n的,意味着如果ai*aj>n那么就对答案无贡献,或者说,对于一个ai,剩下数中可能能对答案产生影响的aj,一定是小于等于n/ai的。

那么我们可以以ai为依据升序排序,先枚举从1到sqrt(n)作为ai,设置一个数组保存bi的数目,然后枚举j,可以很方便地计算ai*aj-bj的数目,如果当前aj==ai的话,说明对应的bi数量++

从小到大排序,避免了第二层循环到j的时候,后面还有可行的ai

现在才知道这玩意叫做“分块”

查看代码

#pragma GCC optimize(2)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
void solve()
{
	ll n,ans=0;
	cin>>n;
	vector<pair<int,int> >a(n);
	for(int i=0;i<n;i++)
		cin>>a[i].first;
	for(int i=0;i<n;i++)
		cin>>a[i].second;
	sort(a.begin(),a.end());//保证将x=i的y的cnt更新,同时只跑一次避免重复
	for(int i=1;i*i<=2*n;i++)
	{
		vector<int>cnt(n+1);//保存a=i时的b=j时的数量
		for(auto [x,y]:a)
		{
			int bj=x*i-y;
			if(bj>=1&&bj<=n)ans+=cnt[bj];//先加再更新避免自加
			if(x==i)
				cnt[y]++;
		}
	}
	cout<<ans<<"\n";
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--)solve();