upper_bound(first, last, value): Returns an iterator pointing to the first element in the range [first,last) which compares greater than val.
lower_bound(first, last, value): Returns an iterator pointing to the first element in the range [first,last) which does not compare less than val.
A - 4 Values whose Sum is 0
we need to find how many quadruplet ( a , b , c , d ) ∈ A × B × C × D (a,b,c,d) \in A \times B \times C \times D (a,b,c,d)∈A×B×C×D satisfy a + b + c + d = 0 a+b+c+d=0 a+b+c+d=0, in other words, we need to find how many equations satisfy a + b = − ( c + b ) a+b=-(c+b) a+b=−(c+b), so we can compute the result of all pairs(a+b), then BinarySearch in the result of all pairs(-(c+b)). time complexity is O ( n 2 l o g n ) O(n^2logn) O(n2logn). In the last lesson, I tell you can use lower_bound() and upper_bound() function in C++ STL instead of implement the corresponding code yourself.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 4e3+100;
struct Quad{
int a, b, c, d;
}quad[maxn];
int ab[maxn*maxn];
int cd[maxn*maxn];
int main(){
int n;
while(scanf("%d", &n) != EOF){
for(int i = 0; i < n; i++)
scanf("%d%d%d%d", &quad[i].a, &quad[i].b, &quad[i].c, &quad[i].d);
int tot = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
ab[tot++] = quad[i].a + quad[j].b;
tot = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
cd[tot++] = -quad[i].c - quad[j].d;
sort(cd, cd+tot);
int ans = 0;
for(int i = 0; i < tot; i++)
ans += upper_bound(cd, cd+tot, ab[i]) - lower_bound(cd, cd+tot, ab[i]);
printf("%d\n", ans);
}
return 0;
}
B - Can you find it?
Similar method to solve this problem.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 505;
int A[maxn], B[maxn], C[maxn];
int check[maxn*maxn];
int main(){
int L, M, N, Case = 0;
while(scanf("%d%d%d", &L, &M, &N) != EOF){
for(int i = 0; i < L; i++) scanf("%d", &A[i]);
for(int i = 0; i < M; i++) scanf("%d", &B[i]);
for(int i = 0; i < N; i++) scanf("%d", &C[i]);
int tot = 0;
for(int i = 0; i < L; i++)
for(int j = 0; j < M; j++)
check[tot++] = A[i] + B[j];
sort(check, check + tot);
int S, X;
scanf("%d", &S);
printf("Case %d:\n", ++Case);
for(int i = 0; i < S; i++){
int flag = 0;
scanf("%d", &X);
for(int j = 0; j < N; j++)
if(binary_search(check, check+tot, X-C[j])){ flag = 1; break;}
if(flag) puts("YES");
else puts("NO");
}
}
return 0;
}
C - Median
First,you can use binary search to find the right median. After than, you should compute how many differences are larger than the median. In this process, because X is in order after sorting, you can also use the idea of binary search。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+100;
#define LL long long
int X[maxn];
bool judge(int n, int val, LL cnt){
LL tot = 0;
for(int i = 0; i < n-1; i++){
tot += n - (lower_bound(X+i, X+n, X[i]+val)-X);
}
return tot > cnt;
}
int main(){
int n;
while(scanf("%d", &n) != EOF){
for(int i = 0; i < n; i++) scanf("%d", &X[i]);
sort(X, X+n);
int l = 0, r = X[n-1]-X[0];
while(l < r){
int mid = (l+r+1)>>1;
if(judge(n, mid, (LL)n*(n-1)>>2)) l = mid;
else r = mid-1;
}
printf("%d\n", r);
}
return 0;
}
D - A Cubic number and A Cubic Number
when you solve this problem, you need to simplify the formula. x 3 − y 3 = ( x − y ) × ( x 2 + x × y + y 2 ) x^3-y^3=(x-y)\times(x^2+x\times y+y^2) x3−y3=(x−y)×(x2+x×y+y2), so when x − y > 1 x-y>1 x−y>1, x 3 − y 3 x^3-y^3 x3−y3 mustn’t be a prime, because it has a divisor ( x − y ) (x-y) (x−y). we draw a conclusion that x − y = 1 x-y=1 x−y=1. After above analytizing, we can store all ( x + 1 ) 3 − x 3 = 3 ∗ i 2 + 3 × i + 1 (x+1)^3-x^3=3*i^2+3\times i+1 (x+1)3−x3=3∗i2+3×i+1 in an array, then binary search corresponding value.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = 1e6+100;
LL cube[maxn], tot = 0;
void init(){
for(LL i = 1; i < maxn; i++)
cube[tot++] = 3*i*i + 3*i + 1;
}
int main(){
init();
int T;
scanf("%d", &T);
while(T--){
LL p;
scanf("%lld", &p);
if(binary_search(cube, cube+tot, p)) puts("YES");
else puts("NO");
}
return 0;
}
E - I Count Two Three
Build table and binary search.
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1e7+5;
LL arr[maxn];
//
int init(){
arr[0] = 1LL;
LL cur = 0;
for(int a = 0; a <= 32; a++)
for(int b = 0; b <= 21; b++)
for(int c = 0; c <= 20; c++)
for(int d = 0; d <= 19; d++){
double x = pow(2.0,a)*pow(3.0,b)*pow(5.0,c)*pow(7.0,d);
if(x > 1e9) continue;
else arr[cur++] = (int)x;
}
sort(arr, arr+cur);
return cur;
}
int main(){
int T, n, right;
right = init();
scanf("%d", &T);
while(T--){
scanf("%d", &n);
int l = 0, r = right-1;
while(l < r){
int mid = (l+r)/2;
if(arr[mid] < n) l = mid+1;
else r = mid;
}
printf("%I64d\n", arr[r]);
}
return 0;
}
F - Pie
#include <stdio.h>
#include <math.h>
#include <algorithm>
const int maxn = 1e4+100;
const double pi = acos(-1.0);
const double eps = 1e-4;
int r[maxn];
int T, N, F;
bool judge(double V){
int tot = 0;
for(int i = 0; i < N; i++){
double x = pi*r[i]*r[i]/V;
tot += floor(x);
}
return tot >= (F+1);
}
double Binary_Search(double R){
//对我和我的朋友所能得到的饼的最大体积进行二分。
double l = 0.0, r = R;
while(fabs(r-l) > eps){
double mid = (l+r)/2.0;
if(judge(mid)) l = mid;
else r = mid;
}
return l;
}
int main(){
scanf("%d", &T);
while(T--){
scanf("%d %d", &N, &F);
int index = 0;
for(int i = 0; i < N; i++){
scanf("%d", &r[i]);
if(r[i] >= r[index]) index = i;
}
printf("%.4lf\n", Binary_Search(pi*r[index]*r[index]));
}
return 0;
}