离散化+二位前缀和的计数题 [USACO20DEC] Rectangular Pasture S

[USACO20DEC] Rectangular Pasture S

显然奶牛坐标最高可达 1 e 9 1e9 1e9, 所以我们先离散化.

cpp 复制代码
for(int i=1;i<=n;P(i)){
	std::cin>>a[i].first>>a[i].second;
	kkk[0].push_back(a[i].first);
	kkk[1].push_back(a[i].second);
}
std::sort(kkk[0].begin(),kkk[0].end());
std::sort(kkk[1].begin(),kkk[1].end());
auto p0=std::unique(kkk[0].begin(),kkk[0].end());
auto p1=std::unique(kkk[1].begin(),kkk[1].end());
kkk[0].erase(p0,kkk[0].end());
kkk[1].erase(p1,kkk[1].end());
for(int i=1;i<=n;P(i)){
	a[i].first=std::lower_bound(kkk[0].begin(),kkk[0].end(),a[i].first)-kkk[0].begin()+1;
	a[i].second=std::lower_bound(kkk[1].begin(),kkk[1].end(),a[i].second)-kkk[1].begin()+1;
	f[a[i].first][a[i].second]=1;
}

显然我们的目的是要去枚举子集. 我们不妨先把坐标排序, 枚举矩形的上下界, 再统计矩形左右两边有相同上下界牛的个数, 相乘即可.

我们以 y y y 为关键字排序, 这样我们就可以直接枚举 y ∈ [ i , j ] y\in[i,j] y∈[i,j] 了.

cpp 复制代码
std::sort(a+1,a+1+n,[](const PII& A, const PII& B){return A.second<B.second;});
for(int i=1,max,min;i<=n;P(i))
for(int j=i;j<=n;P(j)){
	max=a[i].first,min=a[j].first;
	if(max<min)std::swap(max,min);
	ans+=1ll*(f[n][j]-f[max-1][j]-f[n][i-1]+f[max-1][i-1])*1ll*(f[min][j]-f[0][j]-f[min][i-1]+f[0][i-1]);
}

但我们也要注意, 我们要 O ( 1 ) O(1) O(1) 统计牛的数量, 于是我们选择前缀和.

cpp 复制代码
for(int i=1;i<=n;P(i))
	for(int j=1;j<=n;P(j))
		f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];

最终答案补上空集即可.

cpp 复制代码
ans++;

总代码:

cpp 复制代码
#include<iostream>
#include<vector>
#include<algorithm>
#define P(A) A=-~A
typedef std::pair<int,int> PII;
typedef long long LL;
#define NUMBER1 2500
int n,f[NUMBER1+5][NUMBER1+5];
PII a[NUMBER1+5];
LL ans(0);
std::vector<int>kkk[2];
signed main(){
	std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
	std::cout.tie(nullptr);
	std::cin>>n;
	for(int i=1;i<=n;P(i)){
		std::cin>>a[i].first>>a[i].second;
		kkk[0].push_back(a[i].first);
		kkk[1].push_back(a[i].second);
	}
	std::sort(kkk[0].begin(),kkk[0].end());
	std::sort(kkk[1].begin(),kkk[1].end());
	auto p0=std::unique(kkk[0].begin(),kkk[0].end());
	auto p1=std::unique(kkk[1].begin(),kkk[1].end());
	kkk[0].erase(p0,kkk[0].end());
	kkk[1].erase(p1,kkk[1].end());
	for(int i=1;i<=n;P(i)){
		a[i].first=std::lower_bound(kkk[0].begin(),kkk[0].end(),a[i].first)-kkk[0].begin()+1;
		a[i].second=std::lower_bound(kkk[1].begin(),kkk[1].end(),a[i].second)-kkk[1].begin()+1;
		f[a[i].first][a[i].second]=1;
	}
	for(int i=1;i<=n;P(i))
		for(int j=1;j<=n;P(j))
			f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
	std::sort(a+1,a+1+n,[](const PII& A, const PII& B){return A.second<B.second;});
	for(int i=1,max,min;i<=n;P(i))
		for(int j=i;j<=n;P(j)){
			max=a[i].first,min=a[j].first;
			if(max<min)std::swap(max,min);
			ans+=1ll*(f[n][j]-f[max-1][j]-f[n][i-1]+f[max-1][i-1])*1ll*(f[min][j]-f[0][j]-f[min][i-1]+f[0][i-1]);
		}
	std::cout<<ans+1;
	return 0;
}
相关推荐
小O的算法实验室20 小时前
2026年ASOC,基于深度强化学习的无人机三维复杂环境分层自适应导航规划方法,深度解析+性能实测
算法·无人机·论文复现·智能算法·智能算法改进
郭涤生21 小时前
STL vector 扩容机制与自定义内存分配器设计分析
c++·算法
༾冬瓜大侠༿21 小时前
vector
c语言·开发语言·数据结构·c++·算法
Ricky111zzz21 小时前
leetcode学python记录1
python·算法·leetcode·职场和发展
汀、人工智能21 小时前
[特殊字符] 第58课:两个正序数组的中位数
数据结构·算法·数据库架构··数据流·两个正序数组的中位数
liu****21 小时前
第16届省赛蓝桥杯大赛C/C++大学B组(京津冀)
开发语言·数据结构·c++·算法·蓝桥杯
汀、人工智能21 小时前
[特殊字符] 第79课:分割等和子集
数据结构·算法·数据库架构·位运算·哈希表·分割等和子集
汀、人工智能21 小时前
[特殊字符] 第74课:完全平方数
数据结构·算法·数据库架构·图论·bfs·完全平方数
CoderCodingNo21 小时前
【GESP】C++四、五级练习题 luogu-P1177 【模板】排序
数据结构·c++·算法
Proxy_ZZ021 小时前
从零实现LDPC比特翻转译码器:C语言实战与底层逻辑解析
c语言·算法