集训第四周(高效算法设计)J题 (中途相遇法)

Description

The SUM problem can be formulated as follows: given four lists ABCD<tex2html_verbatim_mark> of integer values, compute how many quadruplet (abcd ) AxBxCxD<tex2html_verbatim_mark> are such that a + b + c + d = 0<tex2html_verbatim_mark> . In the following, we assume that all lists have the same size n<tex2html_verbatim_mark> .

Input

The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.

The first line of the input file contains the size of the lists n<tex2html_verbatim_mark> (this value can be as large as 4000). We then have n<tex2html_verbatim_mark> lines containing four integer values (with absolute value as large as 228<tex2html_verbatim_mark> ) that belong respectively to ABC<tex2html_verbatim_mark> and D<tex2html_verbatim_mark> .

Output

For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.

For each input file, your program has to write the number quadruplets whose sum is zero.

Sample Input

1

6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45

Sample Output

5

Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

如果按照原始方法,进行四重循环,毫无疑问是会超时的,只能使用方法把四重循环变成两重,可是每一个数最大可达2的28次方,使用short开数组也是行不通的,做一个大整数的hash。。不会,只能使用数组保存值,之后再进行查找了。。。

#include"iostream"
#include"cstring"
#include"algorithm"
#include"map"
#include"cmath"
using namespace std;
const int maxn=4000+10;
int book[16000010];
int a[maxn],b[maxn],c[maxn],d[maxn];
int main()
{
   int T;
   cin>>T;
while(T--)
  {
   int n;
   cin>>n;
   memset(book,0,sizeof(book));
   for(int i=0;i<n;i++)
   cin>>a[i]>>b[i]>>c[i]>>d[i];

   int f=0;
   for(int ia=0;ia<n;ia++)
    for(int ib=0;ib<n;ib++)
   {
       book[f++]=-(a[ia]+b[ib]);
   }
  int sum=0;
  sort(book,book+f);
  for(int ic=0;ic<n;ic++)
  for(int id=0;id<n;id++)
  {
      int temp=c[ic]+d[id];
      int x1=lower_bound(book,book+f,temp)-book;
      int x2=upper_bound(book,book+f,temp)-book;
      sum+=x2-x1;
  }
   cout<<sum<<endl;
   if(T) cout<<endl;
  }
    return 0;
}
时间: 2024-07-29 04:24:38

集训第四周(高效算法设计)J题 (中途相遇法)的相关文章

第八章 高效算法设计

分治法求最大连续和 注意范围是[x,y) #include<bits/stdc++.h> using namespace std; int maxsum(int *A,int x,int y){ if(y-x==1) return A[x]; int m=x+(y-x)/2; int maxs = max(maxsum(A,x,m),maxsum(A,m,y)); int v,L,R; v=0; L=A[m-1]; for(int i=m-1;i>=x;i--) L=max(L,v+=A

算法优化策略之“中途相遇”算法思想

中途相遇法,这是一种特殊的算法,大体思路是从两个不同的方向来解决问题,最终"汇集"到一起."双向广度优先搜索"算法就有一点中途相遇的味道.下面我们通过一道具体的题目,来了解一下这种算法思想的应用.和为0的4个值(4 Value Whose Sum is Zero,ACM/ICPC SWERC 2005,UVa 1152)给定4个n(1<=n<=400)元素集合A,B,C,D,要求分别从中选取一个元素a,b,c,d,使得a+b+c+d=0.问有多少种选法?

Codeforces Round #297 (Div. 2) E题. Anya and Cubes (中途相遇法)

题目地址:Anya and Cubes 比赛的时候居然没想起中途相遇法...这题也是属于想起来就很简单系列. 中途相遇法也叫折半搜索.就是处理前一半,把结果储存起来,再处理后一半,然后匹配前一半存储的结果. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib

J 中途相遇法,求和

---恢复内容开始--- J - 中途相遇法 Time Limit:9000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Description The SUM problem can be formulated as follows: given four lists A, B, C, D<tex2html_verbatim_mark> of integer values, compute

集训第四周(高效算法设计)M题 (扫描法)

原题:UVA11078 题意:给你一个数组,设a[],求一个m=a[i]-a[j],m越大越好,而且i必须小于j 怎么求?排序?要求i小于j呢.枚举?只能说超时无上限.所以遍历一遍数组,设第一个被减数为a[0],之后遇到比a[0]大的数就更新它,再拿这个被减数去减数组中的每一个元素,同时也要不断地更新这个m值. #include"iostream" #include"set" #include"cstring" #include"cst

集训第四周(高效算法设计)I题 (贪心)

Description Shaass has n books. He wants to make a bookshelf for all his books. He wants the bookshelf's dimensions to be as small as possible. The thickness of the i-th book is ti and its pages' width is equal to wi. The thickness of each book is ei

集训第四周(高效算法设计)A题 Ultra-QuickSort

原题poj 2299:http://poj.org/problem?id=2299 题意,给你一个数组,去统计它们的逆序数,由于题目中说道数组最长可达五十万,那么O(n^2)的排序算法就不要再想了,接下来的选择是快排,归并,看你喜欢了 这里列出归并的解法: #include"iostream" using namespace std; const int maxn=500000+10; int T[maxn]; int a[maxn]; long long sum; void merg

集训第四周(高效算法设计)N题 (二分查找优化题)

原题:poj3061 题意:给你一个数s,再给出一个数组,要求你从中选出m个连续的数,m越小越好,且这m个数之和不小于s 这是一个二分查找优化题,那么区间是什么呢?当然是从1到数组长度了.比如数组长度为10,你先找5,去枚举每一个区间为5的连续的数,发现存在这样的数,那么就可以继续往左找,反之则往右找,直到左右区间重合,即为正确答案,(有可能是右区间小于左区间,所以每次都应该求区间中点值) #include"iostream" #include"set" #incl

集训第四周(高效算法设计)L题 (背包贪心)

Description John Doe is a famous DJ and, therefore, has the problem of optimizing the placement of songs on his tapes. For a given tape and for each song on that tape John knows the length of the song and the frequency of playing that song. His probl