牛客周赛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;
}
相关推荐
PHASELESS4114 分钟前
Java栈与队列深度解析:结构、实现与应用指南
java·开发语言·算法
Nigori7_26 分钟前
day33-动态规划__62.不同路径__63. 不同路径 II __343. 整数拆分__343. 整数拆分
算法·动态规划
SeasonedDriverDG27 分钟前
C语言编写的线程池
linux·c语言·开发语言·算法
2401_8729450934 分钟前
【补题】Codeforces Round 857 (Div. 1) A. The Very Beautiful Blanket
算法
LAOLONG-C37 分钟前
C语言 栈 的 描述 和 详解
c语言·数据结构·算法
Ring__Rain39 分钟前
visual studio 常用的快捷键(已经熟悉的就不记录了)
c++·git·visual studio
辛姜_千尘红回39 分钟前
AT_abc398_e [ABC398E] Tree Game 题解
c语言·c++·笔记·算法
啊阿狸不会拉杆43 分钟前
数据结构-限定性线性表 - 栈与队列
java·c语言·数据结构·c++·python·算法
ChiaWei Lee1 小时前
【C++初学】C++核心编程(一):内存管理和引用
c++
做一个优雅的美男子1 小时前
【力扣05】最长回文子串
算法·leetcode·职场和发展