首页 > 其他分享 >Codeforces Round 967 (Div. 2)

Codeforces Round 967 (Div. 2)

时间:2024-08-21 10:38:30浏览次数:9  
标签:cnt 967 int 回溯 Codeforces ++ ans Div 指针

A. Make All Equal
题意:给定n个数每次可以选2个相邻的数,并且前面的数不能比后面的数大,并且删除其中的一个。这个数组是循环数组,最后一个数是第一个数的前一个数。问最少操作多少次,可以让剩下的数全都相等。

思路:红黑树+一次遍历,记录出现次数最多的数,剩下的数全部删掉即可。

总结:看了一下示例很快就A了,但是不太理解这里要求选数的时候 前面的数不能比后面的数大 这个条件有什么影响。 思考一下,假设有相邻的i,j。i出现的次数最多,i > j,则不能直接删除j,需要考虑j和j + 1,而j + 1和j的大小关系不确定,如果j + 1是要保留的数,那么可以直接删掉j,如果不是要保留的数,那么不在乎大小关系,随便删一个即可。所以到了最后,j的后面的数一定是i,另一种情况当i <= j,直接删掉j。

void solve(){
	int n;
	cin >> n;

	map<int, int> mapp;
	int ans = n + 1;
	for (int i = 0; i < n; ++i) {
		int t;
		cin >> t; 
		mapp[t] ++;
		ans = min(ans, n - mapp[t]);
	}

	cout << ans << '\n';
}

B. Generate Permutation

题意:给定两个指针l和r,初始时分别在数组首末。每次操作可以将指针往对应的方向移动1,或者在当前的下标上将初始值-1改为一个数组未出现最小的正数,或者将指针回溯到起始点。 问是否有一个permutation,不管用左指针构造还是右指针构造,他们回溯到起始点的操作数是相等的。

思路:偶数时无解。 奇数时把1放到数组最中间,然后维护两个指针,一个往右加数,一个往左加数,并在每次移动一个距离后将两个指针的值互换,这样保证左右两个指针在构造时,回溯次数相等。
比如 n = 5
-1 -1 1 -1 -1
-1 3 1 2 -1
5 3 1 2 4
左指针构造要回溯2次,右指针也是两次。

总结:先看测试示例,大概能看出来偶数长度无解。考虑奇数长度,为了让左右指针的回溯次数相等,肯定是中间有一个中位数,剩下的数往两边补,补的过程中要保证左右指针回溯次数相等。而为了保证增加数时,保证指针的回溯次数相等,那肯定是一次考虑增加两个数,如果只增加一个数,必然有一个指针不用回溯。 有了这个思路,直接拿n = 3和n = 5试一下,就知道如何写代码了。

void solve(){
	int n;
	cin >> n;

	if (n % 2 == 0) {
		cout << "-1\n";
	}
	else {
		int m = n / 2;
		int cnt = 1;
		int i = m + 1, j = m - 1;
		vector<int> ans(n);
		ans[m] = 1;
		while (j >= 0) {
			if (j & 1) {
				ans[i] = ++cnt;
				ans[j] = ++cnt;
			}
			else {
				ans[j] = ++cnt;
				ans[i] = ++cnt;
			}
			i ++;
			j --;
		}
		for (int i = 0; i < n; ++i) {
			cout << ans[i] << " \n"[i == n - 1];
		}
	}
}

赛时很快A完2道题,然后开始坐牢,交互题是真不想做啊,看了一遍题目,就没继续了。

D题看错了,把数值范围看成了1~9(我寻思最大最小字典序数字都不超过10啊),然后调试了半个多小时,发现读错题了
直接关机睡觉。

哎 又要掉大分了

D. Longest Max Min Subsequence

题意:给定n个数,求最长的包含不相同元素的满足特定条件的子序列。特定条件:最长子序列中的奇数位*-1后,字典序最小

思路:维护每个数出现的次数一个一个ans数组,然后依次遍历n个数。当遍历到第i个数时,如果ans为空,则加入数到ans,并且标记该数已在ans中出现过,否则循环的考虑ans中的倒数第一个数和倒数第二个数,看当前数在替代某一个数的情况下,是否可以不改变最终ans的长度(通过查看后续数字中是否出现过ans中的这两个数来判定),以及是否会让字典序更小(通过判定奇数偶数位来决定是否当前数字更优,奇数位应该找大数,偶数位找小数),如果更优,则pop出对应的数,否则加当前数加入到数组末尾。

总结:赛时看错题了,以为只有19,于是维护了每个位置下一个19数字出现的次数,并判断当前位是奇数还是偶数位,然后在不改变最终子序列长度的情况下,选个最优的数,结果在调试的时候发现。。范围搞错了。
这个题目的类型,应该属于最长子序列的变种题。最长子序列的经典问题包括最长非递增,非递减,递增递减子序列,要用特有的算法去求解。
对于当前的题目,也可以归结为一种特别的算法,最长不相同元素子序列(好像直接set去重就行,太简单了),那就加个限制,最长递增不相同元素子序列(差不多可以认为是个模板题吧)。

reserve后代码评测使用内存从1400k降到了0,神奇。

void solve(){
    int n;
    cin >> n;
    
    vector<int> a(n);
    vector<int> ans;
    ans.reserve(n);
    for (auto& x : a) {
        cin >> x;
    }

    int s = *max_element(a.begin(), a.end());
    vector<int> cnt(s + 1);
    vector<bool> has(s + 1);
    for (const auto&x : a) {
        cnt[x] ++;
    }

    auto better = [](int x, int y, bool odd) {
        return odd ? x > y : x < y;
    };
    for (int i = 0; i < n; ++i) {
        cnt[a[i]] --;
        if (ans.empty()) {
            ans.push_back(a[i]);
            has[a[i]] = true;
            continue;
        }
        if (has[a[i]]) {
            continue;
        }
        while (!ans.empty()) {
            int m = (int)ans.size();
            if (cnt[ans[m - 1]] && better(a[i], ans[m - 1], m & 1)) {
                has[ans[m - 1]] = false;
                ans.pop_back();
            }
            else if (m > 1 && cnt[ans[m - 2]] && cnt[ans[m - 1]] && better(a[i], ans[m - 2], (m - 1) & 1)) {
                has[ans[m - 2]] = false;
                has[ans[m - 1]] = false;
                ans.pop_back();
                ans.pop_back();
            }
            else {
                break;
            }
        }
        ans.push_back(a[i]);
        has[a[i]] = true;
    }
    cout << ans.size() << '\n';
    for (int i = 0; i < ans.size(); ++i) {
        cout << ans[i] << " \n"[i == ans.size() - 1];
    }
}

标签:cnt,967,int,回溯,Codeforces,++,ans,Div,指针
From: https://www.cnblogs.com/yxcblogs/p/18371113

相关文章

  • CodeForces 360D Levko and Sets
    洛谷传送门CF传送门求出\(p\)的原根\(g\),对每个\(a_i\)求出一个\(x_i\)表示\(g^{x_i}\equiva_i\pmod{p}\)(这部分可以BSGS)。之后的表述中\(a_i\)指\(x_i\)。那么集合生成方式相当于初始\(c=0\),每次让\(c\gets(c+a_ib_j)\bmod(p-1)\)。根据裴蜀定......
  • 【LGR-196-Div.4】洛谷入门赛 #26 题A - H 详细题解--优化思路简洁代码(C++,Python语
    前言:    觉得这个比赛很有意思的,都是暴力题,涉及一些细节,难度比较适合刚学编程语言的,可以很好的锻炼基础还有手速,最后两题也是比较有意思,之后也准备更新atc的比赛题解和洛谷的一些高质量比赛题解(算法网瘾就是想参加各种比赛)   如果觉得有帮助,或者觉得我写的好,......
  • Educational Codeforces Round 168 (Rated for Div. 2) D题
    文章目录题目来源题意思路code题目来源D.MaximizetheRoot题意给定一棵n个点的数,根节点为1,每个点都有权值aia_i......
  • Codeforces Round 966 (Div. 3) (A~F)
    文章目录写在前面A-PrimaryTask思路codeB.SeatinginaBus思路codeC-NumericStringTemplate思路codeD-RightLeftWrong思路codeE-PhotoshootforGorillas思路codeF-ColorRowsandColumns思路codeCodeforcesRound966(Div.3)写在前面赛时写的......
  • CF Round 966 Div3
    A给定一个字符串,判断是不是大于等于10210^2102的形式,例如......
  • Codeforces 169 Div2
    AClosestPoint由题意可得三个及以上的点无法插入新的点,只有两个点时可以插入但当两个点间隔为1时同样无法插入先判断,后输出就行#include<bits/stdc++.h>usingnamespacestd;constintN=50;intt,n;inta[N];intmain(){ cin>>t; while(t--){ cin>>n; for(i......
  • 自创CodeForcesHelperv1.0,解决CF太卡和跳题问题,代码持续更新!
    文章目录前言一、方法二、源代码三、使用方法四、效果展示总结前言对于OIers来说,Codeforces是一个很好的外国OJ。洛谷上确实收录了大部分CF的题,但是最近由于Codeforces的cloudflare加强了,所以洛谷的爬虫已经无法正确爬取提交记录的数据了,详见link。我......
  • [AGC064C] Erase and Divide Game
    link感觉题解说的都很不清晰,这里只谈个人理解。考虑操作的本质是什么,两人从低到高确定二进制下的每一位填的数,并且场上只保留对应后缀的数字,当场上没有数字时当前操作者输。设\(f[i,S]\)表示确定了前\(i\)位,填的数为\(S\),接下来先手是否能赢,那么有\(f[i,S]=\neg(f[i......
  • Codeforces Round 894 (Div. 3) D
    题目:E.KolyaandMovieTheatre题目链接:https://codeforces.com/contest/1862/problem/E思路:主要用优先队列存放大于0的元素,然后除了第一个数据后的每m个数据就可以存放到记录数组里面,最后遍历找价值最大的点击查看代码#include<bits/stdc++.h>#defineintlonglongusing......
  • codeforces ECR169
    codeforcesECR169A#include<bits/stdc++.h>usingnamespacestd;constintmaxn=50;inta[maxn];voidsolve(){intn;cin>>n;for(inti=1;i<=n;i++)cin>>a[i];if(n==2){if((a[2]-a[1])!=1){......