甜甜圈
题意#
艾洛喜欢吃甜食,他有n个甜甜圈,现在叠成了两叠(如下图所示),第一叠有n1个,第二叠有n2个(n1+n2=n),要解决的问题如下:
- 每个甜甜圈都有一个唯一的甜度值
- 甜度值两两不同;
每次艾洛可以把任意一叠位于顶端的一个甜甜圈移动到另一叠顶端,若该甜甜圈是当前所有甜甜圈中最甜的(甜度值最大),那么艾洛不会移动甜甜圈,而是直接吃掉;
请你求出艾洛吃完所有甜甜圈的最小移动步数;
题目样例#
样例输入
3 3
1 4 5
2 7 3
样例输出
6
思路#
我们可以把两叠甜甜圈从顶端拼接成一个甜甜圈.
问题就转化为了按照从大到小的顺序去移动一个指针(指针的初始点在两个甜甜圈的顶端位置)
这个问题可以用树状数组解决
我们模拟一下样例
3 7 2 | 1 4 5 (刚开始的时候指针在中间)
3 | 2 1 4 5 然后指针要移动到最大值(7) 移动了 一次
3 2 1 4 | 然后指针要移动到最大值(5) 移动了 三次
3 2 1 | 然后指针要移动到最大值(4) 移动了 零次
| 2 1 然后指针要移动到最大值(3) 移动了 两次
| 1 然后指针要移动到最大值(2) 移动了 零次
| 然后指针要移动到最大值(1) 移动了 零次
因此呢,问题就转化为了求从最大值到最小值按顺序移动最少需要移动多少次的问题
我们只需要对数组按照大小排一下序,然后用树状数组求得即可
CODE#
#include <cstdio>
#include <algorithm>
#define LL long long
#define lowbit(x) x & -x
#define fi first
#define se second
#define PII pair<int, int>
using namespace std;
const int N = 1e5 + 10;
int n, m, len, tr[N];
PII a[N];
inline void add(int x, int c) {
while(x <= len) {
tr[x] += c;
x += lowbit(x);
}
}
inline int ask(int x) {
int res = 0;
while(x) {
res += tr[x];
x -= lowbit(x);
}
return res;
}
int main() {
scanf("%d%d", &n, &m); len = n + m;
for(int i = m + 1; i <= len; i ++ ) {
int x; scanf("%d", &x);
add(i, 1);
a[i] = {x, i};
}
for(int i = m; i; i -- ) {
int x; scanf("%d", &x);
add(i, 1);
a[i] = {x, i};
}
sort(a + 1, a + 1 + len);
reverse(a + 1, a + 1 + len);
a[0].se = m;
LL ans = 0;
for(int i = 1; i <= len; i ++ ) {
add(a[i].se, -1);
//这里先把它减少就可以避免一个小问题 如果指针和当前的最大值相邻的话,就直接不用考虑移动了
ans += abs(ask(a[i].se) - ask(a[i-1].se));
}
printf("%lld\n", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现