写了个沙雕代码导致一晚上全瞎折腾了,又只出了E,我就想小号上个紫呀,太南了我
E. Alice and the Unfair Game
题意:有 个箱子排成一排,只有一个箱子有桃子,你的目标是不能让 猜到桃子在哪个箱子里, 一共猜了 次,在 每次猜箱子之前和之后,你都能把桃子移动到相邻箱子或者不动,定义 为桃子一开始在 箱子, 猜了 次后桃子在 箱子,求一共有多少个合法的
解法:首先 一定合法,我们枚举 ,找一个最大的 ,使得 合法,那么 ,问题转化成求最大的 ,假设一共有 个箱子, , 猜的箱子分别是 , 猜 之前我不能把桃子移到 号箱子,猜第 之前不能把桃子移动到 号,猜 的之前不能移动到 号箱子去,不难发现猜完后桃子最远可以移动到 号箱子,我们设 为 下一次猜 号箱子,当前桃子在 号箱子,目标尽量把桃子移到最右边去,接下来必须要原地不动 次,不难发现对于 ,我们找到第一个 满足 ,那么 ,处理完 后,我们枚举 ,找到最小的 满足 ,我们有 次移动的机会,那么我们最多可以移到 号箱子去,还有一个问题:求最小的 使得 合法,这个问题我们可以把 变成 后再用之前讲得解法去搞定
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 10;
unordered_map<int, int> mp;
int a[maxn], n, m, d[maxn];
ll calc()
{
ll ans = 0;
for (int i = m; i; i--)
{
int k = a[i] - i - 1;
d[i] = d[mp[k]] + 1;
mp[k + 1] = i;
}
for (int i = 1; i <= n; i++)
{
int k = mp[i];
int T = min(n, i + m + 1 - d[k]);
ans += T - i;
}
return ans;
}
int main()
{
scanf("%d%d", &n, &m);
ll ans = n;
for (int i = 1; i <= m; i++)
scanf("%d", &a[i]);
if (n == 1)
return puts("0"), 0;
ans += calc();
memset(d, 0, sizeof(d));
mp.clear();
for (int i = 1; i <= m; i++)
a[i] = n + 1 - a[i];
ans += calc();
cout << ans;
}