A
Random exchange a [ i ] a[i] a[i] and b [ i ] b[i] b[i], ask m a x { a [ i ] } × m a x { b [ i ] } max\{a[i]\}\times max\{b[i]\} max{a[i]} × Minimum value of max{b[i]}
- Because the closer the two numbers are, the greater the product is, so we try our best to make the large number a a a in the array, let the decimal in b b b array, and then take the product of the maximum value respectively
#include <bits/stdc++.h> using namespace std; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--){ int n; cin >> n; vector<int> a(n), b(n); for(auto &i : a) cin >> i; for(auto &i : b) cin >> i; int mxa = -1; int mxb = -1; for(int i=0;i<n;i++){ if(a[i] < b[i]) swap(a[i], b[i]); mxa = max(mxa, a[i]); mxb = max(mxb, b[i]); } cout << mxa * mxb << '\n'; } return 0; }
B
Give you an array. Now you can do an operation with the following continuous k k Continuous before k-term coverage k k Item k asks the minimum number of operands required to turn this array into the same number
- Obviously, it should be overwritten from back to front, and the value of the last array must be equal to the last number, so you can record the current length and traverse from back to front
#include <bits/stdc++.h> using namespace std; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--){ int n; cin >> n; vector<int> a(n + 1); for(int i=n;i>=1;i--) cin >> a[i]; int ans = 0; int r = 1; for(int i=1;i<=n;i++){ if(a[i] != a[1]){ while(i > r){ r *= 2; ans += 1; } }else{ r = max(r, i); } } cout << ans << '\n'; } return 0; }
C
Let you [ 0 , n − 1 ] [0,n-1] [0,n − 1] this n n n numbers are divided into two groups to meet ∑ a [ i ] & b [ i ] = k \sum a[i]\&b[i]=k Σ a [i] &b [i] = k, guarantee n n n is 2 2 Power of 2, k ∈ [ 0 , n − 1 ] k\in[0,n-1] k∈[0,n−1]
- We know first, because n n n is 2 2 The power of 2, so in this problem, as long as it is satisfied a + b = n − 1 a+b=n-1 a+b=n − 1, or use the inverse and then sum with N, then there is a & b = 0 a\&b=0 a&b=0
- We can consider a construction method if we set c ( k ) c(k) c(k) and k k k constitutes binary complementarity, we only need to choose 0 , n − 1 , c ( k ) , k 0,n-1,c(k),k 0,n − 1,c(k),k can meet the requirements of the topic, because 0 & c ( k ) = 0 , ( n − 1 ) & k = k 0\&c(k)=0,(n-1)\&k=k 0 & C (k) = 0, (n − 1) & K = k, which meets the requirements of the topic, and we let the other numbers find their complementary numbers
- But we need special judgment k = 0 k=0 k=0 and k = n − 1 k=n-1 k=n − 1 because these two special values are used in the above scheme, k = 0 k=0 When k=0, you only need to pair all numbers with their complementary numbers; k = n − 1 k=n-1 When k=n − 1, we can choose these groups of special values ( n − 1 , n − 2 ) , ( n − 3 , 1 ) , ( 0 , 2 ) (n-1,n-2),(n-3,1),(0,2) (n − 1,n − 2),(n − 3,1), (0,2), found here n ≥ 4 n\geq4 n ≥ 4, and n = 4 n=4 Found when n=4 1 1 1 was used twice, so a special judgment was made and it was found that n = 4 , k = 3 n=4,k=3 When n = 4 and K = 3, there is no solution. According to the above construction method, there is only one case without solution, and then the rest choose the one paired with itself
- This question is very clever
#include <bits/stdc++.h> using namespace std; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--){ int n, k; cin >> n >> k; if(n == 4 && k == 3){ cout << -1 << '\n'; continue; } if(k == 0){ vector<bool> vis(n + 1); for(int i=0;i<n;i++){ int now = n - 1 - i; if(vis[i] || vis[now]) continue; cout << i << ' ' << now << '\n'; vis[i] = vis[now] = true; } }else if(k == n - 1){ cout << n - 1 << ' ' << n - 2 << '\n'; cout << n - 3 << ' ' << 1 << '\n'; cout << 0 << ' ' << 2 << '\n'; vector<bool> vis(n + 1); vis[n - 1] = vis[n - 2] = vis[n - 3] = vis[1] = vis[0] = vis[2] = true; for(int i=0;i<n;i++){ int now = n - 1 - i; if(vis[now] || vis[i]) continue; cout << now << ' ' << i << '\n'; vis[now] = vis[i] = true; } }else{ cout << 0 << ' ' << n - 1 - k << '\n'; cout << n - 1 << ' ' << k << '\n'; vector<bool> vis(n + 1); vis[0] = vis[n - 1] = vis[n - 1 - k] = vis[k] = true;; for(int i=0;i<n;i++){ int now = n - 1 - i; if(vis[now] || vis[i]) continue; cout << i << ' ' << now << '\n'; vis[i] = vis[now] = true; } } } return 0; }
D
Let you divide an array into k k k subarray, let you specify a range [ x , y ] [x,y] [x,y], so that the number of elements in this range of element values in each subarray is strictly greater than the number of elements outside this range. Now let y − x y-x y − x is as small as possible. Now there is a scheme to divide several subarrays to find this range
- Suppose we already know x , y x,y x. Y, so how do we divide the array? Enumerate the left endpoint. If it is found that the current subarray meets the requirements, it will be a subarray. In other words, if only one number of the array meets the conditions, it will be a number in the array. The less, the better. Such a construction is legal; If the current number does not meet the conditions, continue to go back until the elements in the array meet the conditions
- The key question now is how to determine x , y x,y x. Y, first of all, let's see how many numbers are there at least [ x , y ] [x,y] [x,y] inside, set as v a l val val, yes v a l ≥ n − v a l + k val\geq n-val+k val ≥ n − val+k, then v a l ≥ n + k 2 val\geq \frac{n+k}{2} val ≥ 2n+k, enumerate the left and right endpoints according to the number of elements, so as to minimize the interval length
- Reference T God code, written really beautiful
#include <bits/stdc++.h> using namespace std; typedef long long ll; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--){ int n, k; cin >> n >> k; vector<int> a(n); for(int i=0;i<n;i++) cin >> a[i]; auto b = a; sort(b.begin(), b.end()); int in = (n + k + 1) / 2; int x = -1; int y = n + 1; for(int i=0;i<=n-in;i++){ int L = b[i]; int R = b[i + in - 1]; if(R - L < y - x){ x = L; y = R; } } cout << x << ' ' << y << '\n'; int mx = -1; int cnt = 0; int last = -1; for(int i=0;i<n;i++){ cnt += ((x <= a[i] && a[i] <= y) ? 1 : -1); if(cnt > mx){ mx = cnt; if(cnt >= 1 && cnt < k){ cout << last + 2 << ' ' << i + 1 << '\n'; last = i; } } } cout << last + 2 << ' ' << n << '\n'; } return 0; }