20250903 S2模拟赛

A. 可爱精灵宝贝

Branimirko是一个对可爱精灵宝贝十分痴迷的玩家。最近,他闲得没事组织了一场捉精灵的游戏。游戏在一条街道上举行,街道上一侧有一排房子,从左到右房子标号由1到n。

刚开始玩家在k号房子前。有m个精灵,第i只精灵在第A[i]栋房子前,分值是B[i],以及它在T[i]秒内(含)存在,之后消失。Branimirko可以选择移动至相邻的房子,耗时1秒。抓住精灵不需要时间,精灵被抓住后消失。时间从第1秒开始。Branimirko能最多获得多少分值和。
Input

输入的第1行为三个正整数n,k,m。

接下来m行描述精灵的信息,分别为A[i],B[i],T[i]。
Output

输出Branimirko能最多获得多少分值和。
Sample Input

10 5 4
1 30 4
3 5 7
7 10 12
9 100 23

Sample Output

115

100%的数据:k≤n≤1000,m≤100,A[i] ≤N,B[i] ≤100,T[i] ≤2000,所有数为正整数。


离散化之后就是关路灯

设f[l][r][t]为所用时间为t,经过了l~r,现在在r的最大分值,g[l][r][t],类似,不过在l

预处理:离散化房屋编号

然后从l~r 向 l-1 ~ r或 l ~ r+1 转移


B. 多米诺

题目描述

大小双王对于多米诺有独特的理解。

现在有一个 n×m 的格子大小的木板,大王想用 1×2 的多米诺骨牌把格子填满。大王不满足于普通的填法,大王还想让每个格点都不能被 4 个多米诺骨牌顶点覆盖。

大小双王想问你有多少个方案把他们填满呢。如果答案太大,对 998244353 取模。
图片

同色为一块多米诺骨牌。图一二为一种合法的装填方案,图三不合法因为黄色点被 4 个多米诺骨牌顶点覆盖了
输入格式

一行两个整数 n,m,表示木板的大小。
输出格式

输出一行一个整数表示答案。
输入样例1

4 4

输出样例1

2

输入样例2

5 100

输出样例2

1050912

对于 100%100% 的数据,满足 1≤n,m≤10^7


n是1e7

看题解,说要转到1维,为什么一定是一维的

因为你考虑第一列(行同理),一定是若干个竖着的然后加一个横着的,否则会无法避免地出现非法情况。

然后横着的那个,你考虑如果没有在尽头结束(放在尽头),那么后面就填不满了(剩余奇数个格子)

所以结论就是一定是由若干个n*k的矩形填充的。

下面是官方题解。

图片
图片


C. 走迷宫

题目描述

大小双王在闯迷宫,尽快熟悉迷宫是一件很重要的事。大王想知道迷宫中有多少条通关的路径。

迷宫是一个 n×m 的网格,每个格子里面有一个数字。一条通关的路径是满足以下条件的路径:

1、大小双王只能走上下左右 4 个方向的相邻格子;

2、大小双王只能走相邻数字比当前格子大 2 的格子;

3、大小双王走的路径长度(走过的格子个数)必须至少为 4;

4、如果周围存在还能继续走的格子,大小双王只能继续走;

5、起点周围不存在比它恰好小 2 的格子。

1≤n,m≤1000, 保证迷宫里的数字绝对值不超过 2×10^6


设f[i][0/1/2/3/4]表示第i个点经过了0123大于等于4的方案数。

连边,建图,然后跑dagDP,拓扑排序转移


图片

2≤n≤100000


ckuBDHSXg_Mixw2cn_sC3

由于题解两个NB的不等式

可以算出来上界

图片
先枚举D

然后枚举两个等差数列的分界点(提前预处理每一个d的每一个前缀和后缀的答案,然后计算答案)

考虑使用对顶堆维护,即一个大根堆维护前1/3小的,一个小根堆维护2/3大的。

#include <iostream>
#include <vector>
#include <queue>
#include <numeric>
#include <algorithm>

using namespace std;

const long long INF = -1;

long long get_cost(long long c, long long x) {
    long long d = x - c;
    if (d < 0) {
        return -d;
    }
    if (d % 2 == 0) {
        return d / 2;
    }
    return (d + 3) / 2;
}

struct CostCalc {
    priority_queue<long long> l_q;
    priority_queue<long long, vector<long long>, greater<long long>> r_q;

    long long s_l = 0;
    long long s_r = 0;
    long long e_l = 0;
    long long o_l = 0;

    int get_l_size() const {
        long long k = l_q.size() + r_q.size();
        return (2 * k + 2) / 3;
    }

    void p_l(long long v) {
        l_q.push(v);
        s_l += v;
        if (v % 2 == 0) e_l++; else o_l++;
    }

    long long pop_l() {
        long long v = l_q.top();
        l_q.pop();
        s_l -= v;
        if (v % 2 == 0) e_l--; else o_l--;
        return v;
    }

    void p_r(long long v) {
        r_q.push(v);
        s_r += v;
    }

    long long pop_r() {
        long long v = r_q.top();
        r_q.pop();
        s_r -= v;
        return v;
    }

    void rebalance() {
        int t_s = get_l_size();
        while (l_q.size() < t_s && !r_q.empty()) {
            p_l(pop_r());
        }
        while (l_q.size() > t_s && !l_q.empty()) {
            p_r(pop_l());
        }
        if (!l_q.empty() && !r_q.empty() && l_q.top() > r_q.top()) {
            long long l_t = pop_l();
            long long r_t = pop_r();
            p_l(r_t);
            p_r(l_t);
        }
    }

    void add(long long v) {
        if (!l_q.empty() && v <= l_q.top()) {
            p_l(v);
        } else {
            p_r(v);
        }
        rebalance();
    }

    long long calc_cost(long long x) const {
        long long k_l = l_q.size();
        long long k_r = r_q.size();
        
        long long c_r = s_r - x * k_r;
        long long c_l = 0;
        long long c_p = x * k_l - s_l;
        
        long long c_diff;
        if (x % 2 == 0) {
            c_diff = o_l;
        } else {
            c_diff = e_l;
        }
        
        c_l = (c_p + 3 * c_diff) / 2;
        
        return c_l + c_r;
    }

    long long query_cost() const {
        if (l_q.empty() && r_q.empty()) return 0;
        if (l_q.empty()) {
            return calc_cost(r_q.top());
        }

        long long mc = l_q.top();
        long long c1 = calc_cost(mc);
        long long c2 = calc_cost(mc - 1);
        
        return min(c1, c2);
    }

    void clear() {
        while (!l_q.empty()) l_q.pop();
        while (!r_q.empty()) r_q.pop();
        s_l = s_r = 0;
        e_l = o_l = 0;
    }
};

void update_min(long long& min_c, long long new_c) {
    if (min_c == INF || new_c < min_c) {
        min_c = new_c;
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    if (!(cin >> n)) return 0;

    if (n <= 2) {
        cout << 0 << '\n';
        return 0;
    }

    vector<long long> a(n);
    long long m_a = 0;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        if (a[i] > m_a) m_a = a[i];
    }
    
    long long d_l = (m_a + n) / max(1, n - 1) + 5;

    long long min_c = INF;

    vector<long long> c(n);
    vector<long long> p_c(n);
    vector<long long> s_c(n);

    CostCalc p_d, s_d;

    for (long long d = -d_l; d <= d_l; d++) {
        for (int i = 0; i < n; i++) {
            c[i] = a[i] - (long long)i * d;
        }

        p_d.clear();
        for (int i = 0; i < n; i++) {
            p_d.add(c[i]);
            p_c[i] = p_d.query_cost();
        }

        s_d.clear();
        for (int i = n - 1; i >= 0; i--) {
            s_d.add(c[i]);
            s_c[i] = s_d.query_cost();
        }

        update_min(min_c, p_c[n - 1]);

        for (int i = 0; i < n - 1; i++) {
            update_min(min_c, p_c[i] + s_c[i + 1]);
        }
    }

    cout << min_c << '\n';

    return 0;
}

posted @ 2025-09-03 21:49  Dreamers_Seve  阅读(25)  评论(0)    收藏  举报