目录
折半枚举
折半枚举是一种很好用的枚举方法,比如有时集合过大无法全部搜索,但刚好只需要他们的和或其他可以处理出的东西,就可以一半一半搜
题1
4 Values whose Sum is 0
传送门:http://poj.org/problem?id=2785
此题就是要求 a+b+c+d=0 的个数
那么 a+b=-(c+d)
只与和有关,所以先把 c+d 的和预处理并排序,当 a+b 值一定时,显然 c+d 值也一定,所以只要二分出
满足c+d=-(a+b) 的 c+d 的个数即可
很容易的样子
以下代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
int n,ans;;
int a[4005],b[4005],c[4005],d[4005],f[16000005];
int main(){
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i]>>b[i]>>c[i]>>d[i];
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
f[(i-1)*n+j]=c[i]+d[j];
sort(f+1,f+n*n+1);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++){
int F=-(a[i]+b[j]);
ans+=upper_bound(f+1,f+n*n+1,F)-lower_bound(f+1,f+n*n+1,F);
}
cout<<ans;
return 0;
}
题2 (NOIP PJ 的题目)
传送门:http://codevs.cn/problem/5624/
可以算是一个折半枚举吧
显然一次处理完 xa,xb,xc,xd 时间不支持
用 ans[x][y] 记录 数x(注意不是第x个)在位置y上出现的次数
那么枚举差值 i ,
再枚举 xa
则 :