D. Pinball
D. Pinball
There is a one-dimensional grid of length . The -th cell of the grid contains a character , which is either '<' or '>'.
When a pinball is placed on one of the cells, it moves according to the following rules:
- If the pinball is on the -th cell and is '<', the pinball moves one cell to the left in the next second. If is '>', it moves one cell to the right.
- After the pinball has moved, the character is inverted (i. e. if used to be '<', it becomes '>', and vice versa).
- The pinball stops moving when it leaves the grid: either from the left border or from the right one.
You need to answer independent queries. In the -th query, a pinball will be placed on the -th cell. Note that we always place a pinball on the initial grid.
For each query, calculate how many seconds it takes the pinball to leave the grid. It can be shown that the pinball will always leave the grid within a finite number of steps.
Input
Each test contains multiple test cases. The first line contains the number of test cases (). The description of the test cases follows.
The first line of each test case contains an integer ().
The second line of each test case contains a string of length consisting of characters '<' and '>'.
It is guaranteed that the sum of over all test cases does not exceed .
Output
For each test case, for each () output the answer if a pinball is initially placed on the -th cell.
Example
input
3
3
><<
4
<<<<
6
<><<<>
output
3 6 5
1 2 3 4
1 4 7 10 8 1
Note
In the first test case, the movement of the pinball for is shown in the following pictures. It takes the pinball seconds to leave the grid.

The movement of the pinball for is shown in the following pictures. It takes the pinball seconds to leave the grid.

解题思路
唉唉,比赛刚结束 分钟就调出来 AC 了。(ノToT)ノ ~┻┻
模拟一下样例就会发现整个过程其实就是在反复横跳,直到最后到达左右边界结束。不管初始时的 是 <
还是 >
,当向左移动遇到 >
或者向右移动遇到 <
都会改变移动方向。所以我们关心的是在整个移动的过程中,会经过 左边哪些 >
以及 右边哪些 <
。
为此我们可以先把所有 <
的下标按顺序存到数组 中,假设有 个。同理把所有 >
的下标按顺序存到数组 中,假设有 个。那么对于第 个询问,就可以在 中二分出小于 的最大下标,假设是 中的第 个元素。同理在 中二分出大于 的最小下标,假设是 中的第 个元素。此时左边有 个 >
,右边有 个 <
。然后分类讨论。
如果 是 <
,模拟一下就会发现当 时最后会走到左边界,左边会经过 中的 >
,右边会经过 中的 <
,考虑如何快速计算中间经过的路程,参考下图:
经过的路程就是 ,等价于 。从而推出更一般的情况:,因此可对 和 预处理前缀和来加速计算。
同理分析 的情况,最后会走到右边界,左边会经过 中的 >
,右边会经过 中的 <
,参考下图:
经过的路程就是 ,等价于 。从而推出更一般的情况:。
是 >
的情况也十分类似,当 时最后会走到右边界,左边会经过 中的 >
,右边会经过 中的 <
,参考下图:
经过的路程就是 。
同理分析 的情况,最后会走到左边界,左边会经过 中的 >
,右边会经过 中的 <
,参考下图:
经过的路程就是 。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5e5 + 10;
char s[N];
int l[N], r[N];
LL sl[N], sr[N];
void solve() {
int n;
scanf("%d %s", &n, s + 1);
int cl = 0, cr = 0;
for (int i = 1; i <= n; i++) {
if (s[i] == '<') l[++cl] = i;
else r[++cr] = i;
}
for (int i = 1; i <= cl; i++) {
sl[i] = sl[i - 1] + l[i];
}
for (int i = 1; i <= cr; i++) {
sr[i] = sr[i - 1] + r[i];
}
for (int i = 1; i <= n; i++) {
int x = prev(lower_bound(r + 1, r + cr + 1, i)) - r;
int y = upper_bound(l + 1, l + cl + 1, i) - l;
if (s[i] == '<') {
if (x <= cl - y + 1) printf("%lld ", i + 2 * (sl[y + x - 1] - sl[y - 1] - sr[x]));
else printf("%lld ", i + n + 1 + 2 * (sl[cl] - sl[y - 1] - (sr[x] - sr[x - (cl - y + 2)])));
}
else {
if (x >= cl - y + 1) printf("%lld ", -i + n + 1 + 2 * (sl[cl] - sl[y - 1] - (sr[x] - sr[x - (cl - y + 1)])));
else printf("%lld ", -i + 2 * (sl[y + x] - sl[y - 1] - sr[x]));
}
}
printf("\n");
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
参考资料
Codeforces Round 930 (Div. 1, Div. 2) Editorial:https://codeforces.com/blog/entry/126513
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18047343
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2023-03-01 D. Serval and Shift-Shift-Shift
2023-03-01 最大数量
2022-03-01 糖果传递
2022-03-01 均值不等式证明
2021-03-01 关于C++中构造函数的常见疑问