Codeforces Round #658 (Div. 2)【没AC的题目】

C,Prefix Flip

题意:有个反转操作 就是你选一个长度n,然后 串a的前n个字符 0变1;1变0;然后前后顺序颠倒。现在就是你需要把a变成b,然后把你每次操作的前缀长度输出出来。
思路:当时做题真的是无厘头啊,题目说一定会有答案,一般这种题目都是有巧的地方吧!
有个思路感觉很好。
把a转成 00…00,全为零的,然后也把b转成00…00;然后输出a的转换过程和b的逆 转换过程。

那么a怎么转换成全0 呢?看下面的例子:
(https://blog.csdn.net/jziwjxjd/article/details/107503946)
当a串等于01011时(下标从1起),如何变成00000?
一、因为第一位是0,不用管一、因为第一位是0,不用管一、因为第一位是0,不用管
二、第二位是1,那么先对[1,1]操作,于是现在变成11011二、第二位是1,那么先对[1,1]操作,于是现在变成11011二、第二位是1,那么先对[1,1]操作,于是现在变成11011
然后对[1,2]操作,于是现在变成00011然后对[1,2]操作,于是现在变成00011然后对[1,2]操作,于是现在变成00011
三、第三位是0,不用管三、第三位是0,不用管三、第三位是0,不用管
四、第四位是1,那先对[1,3]操作,于是现在变成11111四、第四位是1,那先对[1,3]操作,于是现在变成11111四、第四位是1,那先对[1,3]操作,于是现在变成11111
然后对[1,4]操作,于是现在变成00001然后对[1,4]操作,于是现在变成00001然后对[1,4]操作,于是现在变成00001
然后你仔细看一下 他其实就是如果前后两个不一样,那么就转换就可以了!

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <algorithm>
#include <iomanip>
#include <map>
#include <queue>
#include <vector>
#include <set>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
char a[100005], b[100005];
vector<int>ans1, ans2;
int n;
int main()
{
	
	int t; cin >> t;
	while (t--)
	{
		cin >> n >> (a + 1) >> (b + 1);
		ans1.clear(); ans2.clear();
		for (int i = 1;i<=n-1;i++)
		{
			if (a[i]!= a[i+1])
				ans1.push_back(i);
		}
		if (a[n]=='1')
			ans1.push_back(n);
		for (int i = 1; i<=n-1; i++)
		{
			if (b[i] != b[i + 1])
				ans2.push_back(i);
		}
		if (b[n] == '1')
			ans2.push_back(n);
		int s = ans1.size() + ans2.size();
		cout << s << " ";
		for (int i =0; i<ans1.size(); i++)
			cout << ans1[i] << " ";
		for (int i=ans2.size()-1; i>=0; i--)
			cout << ans2[i] << " ";
			cout<<endl;
	}
	
}

这个代码C1 C2都能过!!!!!

D.Unmerge

题意:给你一个数组(长度2*n)。问你这个数组是不是由 两个数组(长度n) 根据merge原则弄出来的。
思路:首先得观察到一个规律,如果某个数的后面紧跟着的数中有一段比他小的数,那么这一段数肯定是在一个数组中的,例: 5 3 1 4 2 10 7 8 9 6 ,那么可以分成三段 [5 3 1] ,[4 2] ,[10 7 8 9 6],那么分段有什么意义呢?
我们知道了可以把这些段分出来,那么我们现在就可以把段自由组合一下,如果能组合成一个长度为n的数组,那么就成立了,如何自由组合?这很像背包dp,代价为段的长度,价值也为段的长度

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <algorithm>
#include <iomanip>
#include <map>
#include <queue>
#include <vector>
#include <set>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int N = 4e3 + 5;
int main()
{
	
	int t; cin >> t;
	while (t--)
	{
		int ans[N], arr[N],dp[N] = { 0 }, n, m = 0;
		cin >> n;
		for (int i = 1; i <= 2 * n; i++)
			cin >> arr[i];
		int maxx = arr[1], num = 1;
		for (int i = 2; i <= 2 * n; i++)
		{
			if (maxx < arr[i])
			{
				maxx = arr[i]; ans[m] = num; m++; num = 0;
			}
			num++;
		}
		for (int i = 0; i < m; i++)
			for (int j = n; j >= ans[i]; j--)
				dp[j] = max(dp[j], dp[j - ans[i]] + ans[i]);
		if (dp[n] == n)
			cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	
	
}

这个题跟0 1背包似的。就是判断段,然后用dp去组合,如果dp【n】==n那么答案就yes else no!

反思:c题没出,太可惜了,感觉如果想到点子上了很简单,还是脑子太笨了,然后c没出没往后看。加油吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值