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];
    }
}
相关推荐
无极低码17 小时前
ecGlypher新手安装分步指南(标准化流程)
人工智能·算法·自然语言处理·大模型·rag
软件算法开发17 小时前
基于海象优化算法的LSTM网络模型(WOA-LSTM)的一维时间序列预测matlab仿真
算法·matlab·lstm·一维时间序列预测·woa-lstm·海象优化
Thera77717 小时前
C++ 高性能时间轮定时器:从单例设计到 Linux timerfd 深度优化
linux·开发语言·c++
罗超驿17 小时前
独立实现双向链表_LinkedList
java·数据结构·链表·linkedlist
superior tigre18 小时前
22 括号生成
算法·深度优先
君义_noip18 小时前
信息学奥赛一本通 1952:【10NOIP普及组】三国游戏 | 洛谷 P1199 [NOIP 2010 普及组] 三国游戏
c++·信息学奥赛·csp-s
努力也学不会java19 小时前
【缓存算法】一篇文章带你彻底搞懂面试高频题LRU/LFU
java·数据结构·人工智能·算法·缓存·面试
旖-旎19 小时前
二分查找(x的平方根)(4)
c++·算法·二分查找·力扣·双指针
ECT-OS-JiuHuaShan19 小时前
朱梁万有递归元定理,重构《易经》
算法·重构