Codeforces Round #593 (Div. 2) E. Alice and the Unfair Game dp

写了个沙雕代码导致一晚上全瞎折腾了,又只出了E,我就想小号上个紫呀,太南了我
E. Alice and the Unfair Game

题意:有 n n 个箱子排成一排,只有一个箱子有桃子,你的目标是不能让 c a t cat 猜到桃子在哪个箱子里, c a t cat 一共猜了 m m 次,在 c a t cat 每次猜箱子之前和之后,你都能把桃子移动到相邻箱子或者不动,定义 ( x , y ) (x, y) 为桃子一开始在 x x 箱子, c a t cat 猜了 m m 次后桃子在 y y 箱子,求一共有多少个合法的 ( x , y ) (x, y)
解法:首先 ( x , x ) (x,x) 一定合法,我们枚举 x x ,找一个最大的 y y ,使得 ( x , y ) (x, y) 合法,那么 a n s + = y x ans+=y-x ,问题转化成求最大的 y y ,假设一共有 6 6 个箱子, x = 1 x=1 c a t cat 猜的箱子分别是 2 , 1 , 3 , 1 , 4 2,1,3,1,4 c a t cat 2 2 之前我不能把桃子移到 2 2 号箱子,猜第 3 3 之前不能把桃子移动到 3 3 号,猜 4 4 的之前不能移动到 4 4 号箱子去,不难发现猜完后桃子最远可以移动到 4 4 号箱子,我们设 d p [ i ] dp[i] c a t cat 下一次猜 a i a_{i} 号箱子,当前桃子在 a i 1 a_{i}-1 号箱子,目标尽量把桃子移到最右边去,接下来必须要原地不动 d p [ i ] dp[i] 次,不难发现对于 a i a_{i} ,我们找到第一个 j ( j > i ) j(j > i) 满足 a i i 1 = a j j a_{i}-i-1=a_{j}-j ,那么 d p [ i ] = d p [ j ] + 1 dp[i] =dp[j]+1 ,处理完 d p dp 后,我们枚举 x x ,找到最小的 i i 满足 a i i = x a_{i}-i=x ,我们有 m + 1 m+1 次移动的机会,那么我们最多可以移到 m i n ( n x + m + 1 d p [ i ] ) min(n,x+m+1-dp[i]) 号箱子去,还有一个问题:求最小的 y y 使得 ( x , y ) (x,y) 合法,这个问题我们可以把 a i a_{i} 变成 n + 1 a i n+1-a_{i} 后再用之前讲得解法去搞定
#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;
}
发布了302 篇原创文章 · 获赞 98 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/ccsu_cat/article/details/102617468