Round 1019(div2) CD

Round 1019(div2)

C - Median Splits(中位数)

题意:把数组分成三段,使得三段的中位数组成的数组的中位数小于等于kkk。

记录sumisum_isumi为前iii个小于等于kkk的个数。然后把满足中位数小于等于kkk的前缀和后缀存下来。

如果最前的前缀和最后的后缀中间至少有一个数,就满足条件了。

否则如果前缀个数或后缀个数大于2也满足条件。再否则讨论两个前缀和两个后缀的情况,如果两个前缀之间中位数小于等于k也满足,后缀同理讨论。

为什么前缀个数大于2就满足条件?

以前缀为例,取最前面的两个合法前缀,如果第一个前缀长度是偶数,那么它到后一个前缀之间的区间也满足,因为它的小于等于k的数正好有一半,所以后一个前缀能满足条件一定是后面出现的小于等于k的数更多。如果第一个前缀长度是奇数,那么下一个满足条件的前缀一定挨着它且这个前缀长度是偶数(因为第一个前缀是最前的,它是奇数那么肯定是单独一个小于等于k的数,那么前两个数就至少有一个数小于等于k了),如果后面还有满足条件的前缀就和上面讨论的一样。所以只要有三个前缀就一定满足。

cpp 复制代码
void solve(){
    int n,k;
    cin>>n>>k;
    vector<int> a(n+1);
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    vector<int> pre(n+1),suf(n+10);
    for(int i=1;i<=n;i++){
        pre[i]=pre[i-1]+(a[i]<=k);
    }
    for(int i=n;i>=1;i--){
        suf[i]=suf[i+1]+(a[i]<=k);
    }
    vector<int> l,r;
    for(int i=1;i<=n;i++){
        if(2*pre[i]>=i)l.push_back(i);
    }
    for(int i=n;i>=1;i--){
        if(2*suf[i]>=(n-i+1))r.push_back(i);
    }
    bool flag =false;
    if((l.size()>2)||(r.size()>2)){
        flag =true;
    }
    if(l.size()==2){
        if(2*(pre[l[1]]-pre[l[0]])>=(l[1]-l[0])){
            flag =true;
        }
    }
    if(r.size()==2){
        if(2*(suf[r[1]]-suf[r[0]]) >=(r[0]-r[1])){
            flag =true;
        }
    }
    if((!l.empty())&&(!r.empty())){
       if(l[0]+1<r[0]){
            flag =true;
        }
    }
    if(flag)cout<<"YES\n";
    else cout<<"NO\n";
}

D Local Construction(思维+构造)

题意:一开始有一个排列,第奇数时刻把所有 pi<=pi−1且pi<=pi+1p_i<=p_{i-1} 且p_i<=p_{i+1}pi<=pi−1且pi<=pi+1的位置保留,其它删去,偶数时刻则是保留pi>=pi−1与pi>=pi+1p_i>=p_{i-1} 与 p_i>=p_{i+1}pi>=pi−1与pi>=pi+1的位置。现在给出每个位置被删掉的时刻,求一个合法的排列。

模拟,按时刻从小到大枚举,把所有这一时刻的数都取出来,分为−1-1−1的左边和右边的两部分。然后如果是奇数时刻左边从大到小给数,右边从小到大给数(类似于-1是二次函数的那个极值点)。偶数时刻左边从小到大,右边从大到小。这样可以保证这些数一定在这一时刻被删掉。

然后最后剩下的一个数给没被删的那个位置。

cpp 复制代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n + 1);
    for (int i = 1; i <= n; ++ i) {
    	std::cin >> a[i];
    }

    std::vector<int> ans(n + 1);

    int m = *std::max_element(a.begin(), a.end());
    int l = 1, r = n;
    for (int i = 1; i <= m; ++ i) {
    	std::vector<int> b[2];
    	int x = 0;
    	for (int j = 1; j <= n; ++ j) {
    		x |= a[j] == -1;
    		if (a[j] == i) {
    			b[x].push_back(j);
    		}
    	}

    	reverse(b[1].begin(),b[1].end());
    	for (auto & j : b[0]) {
    		if (i & 1) {
    			ans[j] = r -- ;
    		} else {
    			ans[j] = l ++ ;
    		}
    	}
    	for (auto & j : b[1]) {
    		if (i & 1) {
    			ans[j] = r -- ;
    		} else {
    			ans[j] = l ++ ;
    		}
    	}
    }
    for (int i = 1; i <= n; ++ i) {
    	if (ans[i] == 0) {
    		ans[i] = l;
    		break;
    	}
    }
    for (int i = 1; i <= n; ++ i) {
    	std::cout << ans[i] << " \n"[i == n];
    }
}
相关推荐
Hcoco_me1 小时前
大模型面试题14:K-means聚类算法全解析(通用场景+深度拓展)
算法·kmeans·聚类
Tim_102 小时前
【C++入门】02、C++程序初识
开发语言·c++
Jay20021112 小时前
【机器学习】30 基于内容的过滤算法
人工智能·算法·机器学习
冰西瓜6002 小时前
分治(二)算法设计与分析 国科大
数据结构·算法
小小晓.2 小时前
Pinely Round 2 (Div. 1 + Div. 2)
c++·算法
清风拂山岗 明月照大江2 小时前
简单文件 IO 示例:使用系统调用读写文件
开发语言·c++·算法
Hcoco_me2 小时前
大模型面试题15:DBSCAN聚类算法:步骤、缺陷及改进方向
算法·数据挖掘·聚类
AI绘画哇哒哒2 小时前
AI 智能体长期记忆系统架构设计与落地实践
人工智能·学习·算法·ai·程序员·产品经理·转行