折半枚举
#include<cstdio> #include<algorithm> using namespace std; const int maxn=4000; int n; int A[maxn],B[maxn],C[maxn],D[maxn]; int CD[maxn*maxn]; void solve() { for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) CD[i*n+j]=C[i]+D[j]; sort(CD,CD+n*n); long long ans=0; for(int i=0; i<n; ++i) { for(int j=0; j<n; ++j) { int cd=-A[i]-B[j]; ans += upper_bound(CD, CD+n*n, cd) - lower_bound(CD, CD+n*n, cd); } } printf("%lld\n",ans); } int main() { scanf("%d",&n); for(int i=0; i<n; ++i) { scanf("%d%d%d%d",&A[i],&B[i],&C[i],&D[i]); } solve(); return 0; }
卡STL,老实手写吧 [em:14]
此题用二分的话速度非常慢,这里用哈希表写,不知道的同学可以百度一下,一种以常数时间插入和查找的数据结构
#include<stdio.h> #include<stdlib.h> #include<stdbool.h> #define HASHSIZE 19999999//19999999是一个素数 #define N 4005 #define MAX (1<<29) //绝对值小于2^28则用一个大数MAX来保护下标 typedef long l; typedef struct Hash { l key, size;//关键字和出现的次数 struct Hash*next; }hash;//用拉链法解决冲突,这里才用linked-list,我看了别人的答案有用数组实现的,好像更快?? hash*hashing[HASHSIZE];//hash表 l a[N], b[N], c[N], d[N], n, ans; hash*findhash(l n) { l a = n % HASHSIZE; hash*p = hashing[a]; while (p)//查找链表。用平衡树更快,不过这个代码量。。。 if (p->key == n) return p; else p = p->next; return NULL; } hash*newhash(l n)//建立新节点 { hash*node = (hash*)malloc(sizeof(hash)); node->key = n; node->size = 1; node->next = NULL; return node; } void addhash(l n) { hash*p = findhash(n); int a = n % HASHSIZE;//采用直接取余法,优点:快 if (p)//假如出现过 p->size++;//次数加一 else {//没出现过,创建新节点 插入链表头部 hash*pnode = hashing[a]; hashing[a] = newhash(n); hashing[a]->next = pnode; } } int main() { scanf("%ld", &n); for (l i = 1; i <= n; i++) scanf("%ld%ld%ld%ld", &a[i], &b[i], &c[i], &d[i]); for (l i = 1; i <= n; i++) for (l j = 1; j <= n; j++) addhash(MAX + a[i] + b[j]); for (l i = 1; i <= n; i++) for (l j = 1; j <= n; j++) { hash*p = findhash(MAX - c[i] - d[j]); if (p)//假如出现过 ans += p->size;//加上出现的次数 } printf("%ld\n", ans); }
折半枚举
卡STL,老实手写吧
[em:14]
此题用二分的话速度非常慢,这里用哈希表写,不知道的同学可以百度一下,一种以常数时间插入和查找的数据结构