zoukankan      html  css  js  c++  java
  • hihocoeder1384

    hihocoeder1384

    算法竞赛进阶指南上的题目

    我们肯定是吧最大值和最小值匹配,次大值和次小值匹配以此类推

    首先,类似于区间覆盖的思想,我们对于一个(L),找到最大的满足条件的(R)

    之后把(R + 1)作为下一个(L)继续这个操作

    现在,问题转化成了我们如何寻找最大的(R)

    一个比较明显的思路就是去二分,但是二分时间复杂度不对

    因为如果每次只能前进一格,二分时间复杂度就变成了(n^2log{n})

    考虑倍增的思想

    我们对于每个(L)

    初始设置(R= L - 1,p = 1)

    之后求加上([R + 1,R + p])时候合法

    合法的话 (p = p imes 2)

    否则 (p = p / 2)

    每次暴力判断新加入的区间是否合法

    可以证明这样时间复杂度

    (nlog^2{n})

    之后发现,对于新加进来的区间,我们只需要把它排序,然后和原有的区间进行归并即可

    时间复杂度就变成了(nlog n)

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<vector>
    #include<ctime>
    #include<cmath>
    #define LL long long
    #define pii pair<int,int>
    #define mk make_pair
    #define fi first
    #define se second
    #define min std::min
    #define max std::max
    const int N = 5e5 + 3;
    int a[N];
    int n,m;LL k;
    std::vector <int> A,B,G;
    inline LL read(){
    	LL v = 0,c = 1;char ch = getchar();
    	while(!isdigit(ch)){
    		if(ch == '-') c = -1;
    		ch = getchar();
    	}
    	while(isdigit(ch)){
    		v = v * 10 + ch - 48;
    		ch = getchar();
    	}
    	return v * c;
    }
    inline bool check(int l,int r){
    	B.clear(),G.clear();
    	for(int i = l;i <= r;++i) B.push_back(a[i]);
    	sort(B.begin(),B.end());
    	int now1 = 0;int now2 = 0;
    	while(now1 < A.size() && now2 < B.size()){
    		if(A[now1] < B[now2]) G.push_back(A[now1++]);
    		else G.push_back(B[now2++]);
    	}
    	while(now1 < A.size()) G.push_back(A[now1++]);
    	while(now2 < B.size()) G.push_back(B[now2++]);
    	LL res = 0;
    	now1 = 0,now2 = G.size() - 1;
    	for(int cnt = 0;cnt < m && now1 < now2;now1++,now2--,cnt++) res += 1ll * (G[now1] - G[now2]) * (G[now1] - G[now2]); 
    	if(res <= k){
    		A = G;
    		return 1;
    	}
    	else return 0;
    }
    int main(){
    	//	freopen("A.in","r",stdin);
    //	freopen("A1.out","w",stdout);
    	int T = read();
    	while(T--){
    		int ans = 0;
    		n = read(),m = read(),k = read();
    		for(int i = 1;i <= n;++i) a[i] = read();
    		int l = 1,r = 0;
    		while(l <= n){
    			int p = 1;
    			A.clear();
    			while(p){
    				int t = min(n,r + p);
    				if(check(r + 1,t)){
    					r = t;
    					if(t == n) break;	
    					p <<= 1;
    				}
    				else p >>= 1;
    			}
    			l = r + 1;
    			ans++;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    /*
    1
    10 2 10
    4 1 3 2 1 3 2 1 3 4 
    
    
    */
    
    
  • 相关阅读:
    IDEA复制module
    input输入框限制输入数字(含小数)
    毕设周总结---3
    皮尔森相关系数算法
    毕设周总结---2
    毕设周总结---1
    解释器模式实例
    架构模式——解释器模式
    课后作业---质量属性
    软件架构师如何工作
  • 原文地址:https://www.cnblogs.com/wyxdrqc/p/11633954.html
Copyright © 2011-2022 走看看