POJ 2785 4 Values whose Sum is 0(中途相遇法)

题目链接:POJ 2785 4 Values whose Sum is 0(中途相遇法)

  • 中途相遇法,还有一个名字感觉更加妥帖一点,叫:折半枚举。 有时候,当问题的规模较大时,无法枚举所有元素的组合,但能够枚举一半的元素组合,此时,将问题拆成两半后分别枚举,再合并他们的结果这一方法往往非常有效。

  • lower_bound(frst, last, val) 用来寻找在数组或容器的 [first, last) 范围内第一个值大于等于 val 的元素的位置,如果是数组,则返回该位置的指针;如果是容器,则返回该位置的迭代器。

  • upper_bound(first, last, val) 用来寻找在数组或容器的 [first, last) 范围内第一个值大于 val 的元素的位置,如果是数组,则返回该位置的指针;如果是容器,则返回该位置的选代器。
    在这里插入图片描述

两重循环加二分,总复杂度为n^2logn

#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
typedef long long ll;

using namespace std;
const int MOD = 10000007;
const int INF = 0x3f3f3f3f;
const int maxn = 4010;
int a[maxn];
int b[maxn];
int c[maxn];
int d[maxn]; 
int ab[maxn*maxn];

int main()
{
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++)
		scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
		
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			ab[i*n+j] = a[i]+b[j];
	
	sort(ab,ab+n*n);
	int cnt = 0;
	
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			int tmp = c[i]+d[j];
			cnt += upper_bound(ab,ab+n*n,-tmp) - lower_bound(ab,ab+n*n,-tmp);
		}
	}
	
	printf("%d\n",cnt);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/89520023
今日推荐