|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 柿子饼同学 于 2024-6-29 21:44 编辑
AcWing.109
提交 3 次
用时 2 h
知识点
倍增 归并
思路
倍增找到下一个端点看看能否满足, 满足 len *= 2 ed += len , 不满足就 len /= 2
本题用倍增的好处:
二分的总时间复杂度是 O(nlogn)
但是最坏要执行 n 次二分, 所以复杂度 O(n^2 logn)
但是倍增:
假设答案的划分区间长度为 l1, l2, ...
那每个 l 都需要 logl 次倍增, 归并是 O(l) 的
所以总的就是 O(nlogn)
(不太会复杂度证明这块的, 答案也看不懂 qwq)
需要进步的地方
码力需要增强, 别人的代码很精简, 我的却很长
每次想问题的时候把具体步骤写下来, 必须要细化
代码
- #include <bits/stdc++.h>
- using namespace std;
- const int N = 5e5 + 5;
- typedef unsigned long long ll;
- int cas;
- int n, m;
- ll a[N], b[N], temp[N], cnt, t;
- bool getval(int l, int mid, int r){ // [l, r) 的值
- // Sort
- cnt = 0;
- for(int i = l; i < r; i++) b[i] = a[i];
- sort(b + mid, b + r);
- // Merge
- int i = l, j = mid, k = 0;
- while(i < mid && j < r){
- if(b[i] < b[j]) temp[k++] = b[i], i++;
- else temp[k++] = b[j], j++;
- }
- while(i < mid) temp[k++] = b[i], i++;
- while(j < r) temp[k++] = b[j], j++;
- // Val
- ll res = 0;
- for(int i = 0; i < m && i < k; i++, k--){
- res += (temp[i] - temp[k - 1])*(temp[i] - temp[k - 1]);
- }
- return (res <= t);
- }
- int main(){
- ios::sync_with_stdio(0);
- cin.tie(0);
- cin >> cas;
- while(cas--){
- cin >> n >> m >> t;
- for(int i = 0; i < n; i++) cin >> a[i];
- ll ans = 0;
- int st = 0, ed = 0;
- while(ed < n){
- int len = 1;
- while(len){
- if(ed + len <= n && getval(st, ed, ed + len)){
- ed += len;
- len <<= 1;
- if(ed > n) break;
- for(int i = st; i < ed; i++){
- a[i] = temp[i - st];
- }
- }
- else{
- len >>= 1;
- }
- }
- st = ed;
- ans++;
- }
- cout << ans << '\n';
- }
- return 0;
- }
复制代码
|
|