HihoCoder - 1384 题解
Advanced CPU Manufacturer (ACM) is one of the best CPU manufacturer in the world. Every day, they manufacture n CPU chips and sell them all over the world.
As you may know, each batch of CPU chips must pass a quality test by the QC department before they can be sold. The testing procedure is as follows:
1) Randomly pick m pairs of CPU chips from the batch of chips (If there are less than 2m CPU chips in the batch of chips, pick as many pairs as possible.)
2) For each pair, measure the Relative Performance Difference (RPD) between the two CPU chips. Let Di be the RPD of the i-th pair
3) Calculate the Sqared Performance Difference (SPD) of the batch according to the following formula:
SPD=∑Di2
If there are only 1 CPU in a batch, then the SPD of that batch is 0.
4) The batch of chips pass the test if and only if SPD≤k, where k is a preseted constant
Usually they send all the n CPU chips as a single batch to the QC department every day. As one of the best CPU manufacturer in the world, ACM never fail the test. However, with the continuous improvement of CPU performance, they find that they are at risk!
Of course they don't want to take any risks. So they make a decision to divide the n chips into several batches to ensure all of them pass the test. What’s more, each batch should be a continuous subsequence of their productions, otherwise the QC department will notice that they are cheating. Quality tests need time and money, so they want to minimize the number of batches.
Given the absolute performance of the n chips P1 ... Pn mesured by ACM in order of manufacture, your task is to determine the minimum number of batches to ensure that all chips pass the test. The RPD of two CPU chips equals to the difference of their absolute performance.
InputThe first line contains a single integer T, indicating the number of test cases.
In each test case, the first line contains three integers n, m, k. The second line contains n integers, P1 ... Pn.
T≤12
1≤n,m≤5×105
0≤k≤1018
0≤Pi≤220
For each test case, print the answer in a single line.
Sample Input
2 5 1 49 8 2 1 7 9 5 1 64 8 2 1 7 9
Sample Output
2 1
思路一:对于每个起点,我们肯定要贪心地找到最大的一个右端点,使得其合法,这样一定是一个最优解。那么对于每个起点,二分终点,然后check,check时需要排序,每次check时间复杂度nlogn,因总共可能有O(n)段(最坏情况),
故时间复杂度n*n*logn*logn.
思路二:与一类似,不二分,换用倍增,因为每次找最大区间时,最坏排序2倍的合法长度,所以叠加起来时间复杂度n*logn*logn。但仍不足以通过此题。
思路三:在思路二的基础上,每次不重新排序,而考虑归并的思想,将倍增产生的新段排序,再与旧段合并,李煜东在蓝书上说这是nlogn的,感觉有待商榷,但运行确实快了不少,足以通过此题。
1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T; 42 */ 43 44 int get_int() { 45 int res = 0; char c = getchar(); 46 while (!isdigit(c)) c = getchar(); 47 while (isdigit(c)) { 48 res = res * 10 + c - '0'; 49 c = getchar(); 50 } 51 return res; 52 } 53 int t, n, m, p[500015], b[500015], c[500015], d[500015]; 54 ll k; 55 void merge_sort(int s, int e, int l) { 56 for (int i = e + 1; i <= e + l; ++i) { 57 c[i] = p[i]; 58 } 59 sort(c + e + 1, c + e + l + 1); 60 int i = s, j = e + 1, o = s; 61 while (i <= e && j <= e + l) { 62 if (b[i] < c[j]) d[o++] = b[i++]; 63 else d[o++] = c[j++]; 64 } 65 while (i <= e) d[o++] = b[i++]; 66 while (j <= e + l) d[o++] = c[j++]; 67 } 68 bool check(int s, int e, int l) { 69 merge_sort(s, e, l); 70 ll tcnt = 0; 71 for (int j1 = s, j2 = e + l; j1 < j2 && j1 - s < m; ++j1, --j2) { 72 tcnt += (ll)(d[j2] - d[j1]) * (d[j2] - d[j1]); 73 if (tcnt > k) { 74 return false; 75 } 76 } 77 for (int i = s; i <= e + l; ++i) { 78 b[i] = d[i]; 79 } 80 return true; 81 } 82 int main() { 83 scanf("%d", &t); 84 while (t--) { 85 scanf("%d%d%lld", &n, &m, &k); 86 for (int i = 1; i <= n; ++i) p[i] = get_int(); 87 int ans = 0; 88 for (int s = 1, e = 0, l = 1; s <= n; ) { 89 int flag = check(s, e, l); 90 //printf("s = %d, e = %d, l = %d, flag = %d\n", s, e, l, flag); 91 if (flag) { 92 e = e + l; 93 if (e == n) { 94 ++ans; 95 break; 96 } 97 l <<= 1; 98 while (e + l > n) l >>= 1; 99 } else { 100 l >>= 1; 101 } 102 if (!l) { 103 ++ans; 104 s = e + 1; 105 l = 1; 106 } 107 } 108 printf("%d\n", ans); 109 } 110 return 0; 111 }