牛客周赛88

目录

[D. 漫步](#D. 漫步)

[E. 密藏](#E. 密藏)

[F. 回响](#F. 回响)


D. 漫步

x + z 中包含了所有 x 中为 1 的二进制位,也就是说 x 加上 z 后不能破坏 x 中本身二进制位为 1 的位,因此只要找到 x 的二进制位中第一个为 0 的位,让这一位为 1,赋值给 z 即可。

cnt 是实际位数,pos 是处于第几位,但 pos 是从 0 开始的,二进制表示中最低位是第 0 位。所以最高位实际上是 cnt - 1。

复制代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 5, INF = 1e18;

int T, n, ans;
string s;

int fpow(int a, int b)
{
	int res = 1;
	while (b)
	{
		if (b & 1)
			res *= a;
		a *= a;
		b >>= 1;
	}
	return res;
}

signed main()
{
	cin >> T;
	while (T --)
	{
		int x;
		cin >> x;
		int cnt = 0, pos = 0;
		int tx = x;
		while (tx != 0)
			tx >>= 1, cnt ++;        // 计算 x 的二进制表示有多少位
		while (x & 1)
			x >>= 1, pos ++;         // 找到第一个为 0 的二进制位
		if (pos == cnt)              // 因为 pos 是从下标 0 开始,所以这里两个相等就已经是超过了最高位了
		{
			cout << "-1" << '\n';
			continue;
		}
		int z = fpow(2, pos);
		cout << z << '\n';
	}
	return 0;
}

E. 密藏

凡是想到用贪心做的,都先想一想能不能 dp。

dp [ i ] [ 0 / 1 ] 表示到前 i 号点的最大收益,0 和 1 分别表示两个世界。dp 的无后效性是指对于前 i 个点的答案,与 i 之后的点无关。每一个 i 都是存的以第 i 号点为终点的最优解。

定义好 dp 之后就是枚举状态转移的所有情况。每一个点都可以由当前世界的前一个点或者另外一个世界的前一个点转移来,区别是后者要加判断条件。因为每个点都可能有两种转移来的方式,所以要取 max。

复制代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5, INF = 1e18;

int T, n, k, ans, a[N], b[N], dp[N][2];
string s;

signed main()
{
	cin >> n >> k;
	for (int i = 1; i <= n; i ++)
		cin >> a[i];
	for (int i = 1; i <= n; i ++)
		cin >> b[i];
	for (int i = 1; i <= n; i ++)
		dp[i][0] = -1, dp[i][1] = -1;
	dp[1][0] = a[1];
	for (int i = 2; i <= n; i ++)
	{
		if (dp[i - 1][0] != -1)
		{
			dp[i][0] = dp[i - 1][0] + a[i];
			if (dp[i - 1][0] - k >= 0)
				dp[i][1] = dp[i - 1][0] - k + b[i];
		}
		if (dp[i - 1][1] != -1)
		{
			dp[i][1] = max(dp[i][1], dp[i - 1][1] + b[i]);
			if (dp[i - 1][1] - k >= 0)
				dp[i][0] = max(dp[i][0], dp[i - 1][1] - k + a[i]);
		}
	}
	ans = max(dp[n][0], dp[n][1]);
	cout << ans;
	return 0;
}

F. 回响

先处理第一堆石子前面的格子,然后处理第一堆到最后一堆,最后处理最后一堆以及后面的所有。

对于夹在有石子的格子中间的空格,就是受到两端石子数的限制,因此看一下距离能否满足,只可长不可短,如果长还要看奇偶性能否满足加一减一微调。

复制代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5, INF = 1e18;

int T, n, cnt, ans[N], a[N], b[N], pos[N];
string s;

signed main()
{
	cin >> n;
	for (int i = 1; i <= n; i ++)
	{
		cin >> a[i];
		if (a[i] != 0)
		{
			cnt ++;
			b[cnt] = a[i];
			pos[cnt] = i;
		}
	}
	if (pos[1] != 1)
		for (int i = 1; i < pos[1]; i ++)
			ans[i] = b[1] + pos[1] - i;
	for (int i = 1; i < cnt; i ++)
	{
		ans[pos[i]] = b[i];
		int t1 = abs(b[i + 1] - b[i]), t2 = pos[i + 1] - pos[i];
		if (t1 > t2)
		{
			cout << "-1";
			return 0;
		}
		if ((t2 - t1) % 2 != 0)
		{
			cout << "-1";
			return 0;
		}
		int cnt = 1;
		for (int j = pos[i] + 1; j < pos[i + 1]; j ++)
		{
			if (cnt <= t1)
			{
				if (b[i] < b[i + 1])
					ans[j] = b[i] + cnt;
				else
					ans[j] = b[i] - cnt;
				cnt ++;
			}
			else
			{
				if (ans[j - 1] == b[i + 1])
					ans[j] = ans[j - 1] - 1;
				else
					ans[j] = ans[j - 1] + 1;
			}
		}
	}
	ans[pos[cnt]] = b[cnt];
	for (int i = pos[cnt] + 1; i <= n; i ++)
		ans[i] = ans[i - 1] + 1;
	for (int i = 1; i <= n; i ++)
		cout << ans[i] << ' ';
	return 0;
}
相关推荐
蒹葭玉树几秒前
【C++上岸】C++常见面试题目--操作系统篇(第二十八期)
linux·c++·面试
醉颜凉几秒前
【LeetCode】打家劫舍III
c语言·算法·leetcode·树 深度优先搜索·动态规划 二叉树
达文汐3 分钟前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
一匹电信狗3 分钟前
【LeetCode_21】合并两个有序链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
User_芊芊君子3 分钟前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
算法_小学生5 分钟前
LeetCode 热题 100(分享最简单易懂的Python代码!)
python·算法·leetcode
执着2595 分钟前
力扣hot100 - 234、回文链表
算法·leetcode·链表
Gorgous—l7 分钟前
数据结构算法学习:LeetCode热题100-多维动态规划篇(不同路径、最小路径和、最长回文子串、最长公共子序列、编辑距离)
数据结构·学习·算法
熬夜造bug7 分钟前
LeetCode Hot100 刷题路线(Python版)
算法·leetcode·职场和发展
2401_8384725129 分钟前
C++中的访问者模式
开发语言·c++·算法