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];
    }
}
相关推荐
楚识科技3 小时前
票据 OCR 识别技术深度解析:从算法原理到企业级落地实现
算法·ocr
longlongzihan3 小时前
LeetCode 25. K 个一组翻转链表 (迭代+分组反转法)
算法·leetcode·链表
xuxigifxfh3 小时前
牛客:BISHI8 大整数哈希
java·算法·哈希算法
涉密IT资质笔记3 小时前
涉密资质投入产出分析模型:时间成本、四块成本构成与 ROI 决策框架
java·开发语言·算法
木井巳3 小时前
【BFS 解决拓扑排序】火星词典
java·算法·leetcode·广度优先·宽度优先·图搜索算法
fpcc3 小时前
c++编程实践—thread_local变量的应用
c++
北风toto4 小时前
KMP 算法详解:从暴力匹配到 O(n+m) 的字符串搜索
java·开发语言·算法
沫璃染墨4 小时前
《从零入门数据结构与算法(二):线性表详解——从顺序表原理到静态与动态实现》
c语言·数据结构·顺序表
j7~4 小时前
【仿 RabbitMQ 项目】发布订阅消息队列 (篇九):队列数据管理,内存镜像 + SQLite 持久化实现
数据库·c++·分布式·sqlite·rabbitmq·队列数据管理
dtq04244 小时前
C++ - 变量
开发语言·c++