T1

发现 $u\to v$ 的方案数是可以用 $u\to k\to v$ 算出来的,就类似 Floyd 枚举中心点。

然后就直接枚举 $gap$,$u\to u+gap$ 枚举中间点进行转移。

但是发现 $1\to 2\to 3\to 5$ 是会统计两次 $1\to {\color{red}2}\to 3\to 5$ 和 $1\to 2\to {\color{red}3}\to 5$ 的。

设 $g_{u,v}$ 表示是否存在 $u\to v$ 的直接连接路径即可顺利转移。

#include <bits/stdc++.h>
using namespace std;
int n;
char mp[1020][1020];
int f[1020][1020];
int g[1020][1020];
int ans;
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
            mp[i][j] = '0';
        for (int j = i + 1; j <= n; j++)
            cin >> mp[i][j];
    }
    // for (int i = 1; i <= n; i++)
    //     for (int j = 1; j <= n; j++)
    //         cout << mp[i][j] << " \n"[j == n];
    for (int gap = 1; gap <= n; gap++)
    {
        for (int u = 1; u + gap <= n; u++)
        {
            int v = u + gap;
            // cout << u << " " << v << endl;
            for (int k = u + 1; k < v; k++)
                (f[u][v] += g[u][k] * f[k][v]) %= 2;
            // cout << f[u][v] << " " << mp[u][v] << endl;
            if ((f[u][v] & 1) != (mp[u][v] ^ '0'))
                (f[u][v] += 1) %= 2, g[u][v] = 1, ans++;
            // cout << f[u][v] << endl
            //      << endl;
        }
    }
    cout << ans << endl;
    return 0;
}

T2

人类智慧

记忆化搜索,$g_u$ 表示 $u$ 出发的最长路,$f_u$ 表示 $u$ 出发最长路中字典序最小的收益。

然后发现字典序不是很好转移,考虑第一步一样取答案最小。喜提过了 19 个然后 WA on #20。

主播赛时到这里就跳了,然后发现

https://www.luogu.com.cn/blog/679936/au-t2-xian-xing-zuo-fa-post

我们记录两步就行了。

WA on #20

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <typename T>
void read(T &x)
{
    x = 0;
    int f = 1;
    char c = getchar();
    for (; c < '0' || c > '9'; c = getchar())
        if (c == '-')
            f = -f;
    for (; c >= '0' && c <= '9'; c = getchar())
        x = x * 10 + c - '0';
    x *= f;
}
template <typename T, typename... Args>
void read(T &x, Args &...y)
{
    read(x);
    read(y...);
}
template <typename T>
void chkmx(T &x, T y) { x = max(x, y); }
template <typename T>
void chkmn(T &x, T y) { x = min(x, y); }
typedef pair<ll, ll> pii;
int n, m;
set<pii> e[200020];
ll f[200020];
ll g[200020];
ll len;
pii dfs(int u, int len)
{
    ll &t = f[u];
    ll &T = g[u];
    if (~t)
        return {t, T};
    if (e[u].empty())
        return {t = 0, T = 0};
    ll val = -1;
    for (pii i : e[u])
    {
        dfs(i.second, len + 1);
        ll res = i.first + f[i.second];
        if (g[i.second] + 1 > T)
            val = i.first, t = res, T = g[i.second] + 1;
        else if (g[i.second] + 1 == T && val == i.first)
            chkmn(t, res);
    }
    return {t, T};
}
int main()
{
    read(n, m);
    while (m--)
    {
        int x, y, z;
        read(x, y, z);
        e[x].insert({z, y});
    }
    memset(f, -1, sizeof(f));
    for (int i = 1; i <= n; i++)
    {
        pii res = dfs(i, 0);
        cout << res.second << " " << res.first << '\n';
    }
    return 0;
}

AC

别急,等发数据了再发。顺便去你谷加强一下。

正解

拓扑。

等我先学习一下。

T3

在线

发现按题目说的 $f(y)$ 就是个凹函数。

容易发现对于整数 $y$ 当 $a\neq b$ 时不存在非极值点的平台,只有在 $a=b$ 时存在平台,但此时函数是一条直线。

整数三分成立,贺板子。

然后考虑优化 $f(y)$ 的计算,稍微拆一下就知道记录前缀和后缀和即可,二分当前 $y$ 在 $x$ 序列中的位置即可单次 $f(y)$ 做到 $\log n$ 的效率,总过程是 $\log^2$ 的。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, q;
int x[200020];
ll pre[200020];
ll suf[200020];
ll a, b;
ll f(ll k)
{
    int pos = upper_bound(x + 1, x + n + 1, k) - x - 1;
    //[1,pos] [pos+1,n]
    return a * (k * pos - pre[pos]) + b * (suf[pos + 1] - k * (n - pos));
}
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> x[i];
    sort(x + 1, x + n + 1);
    for (int i = 1; i <= n; i++)
        pre[i] = pre[i - 1] + x[i];
    for (int i = n; i >= 1; i--)
        suf[i] = suf[i + 1] + x[i];
    cin >> q;
    while (q--)
    {
        cin >> a >> b;
        int l = 0, r = 1e6 + 1;
        while (l < r)
        {
            int ml = l + (r - l) / 3;
            int mr = r - (r - l) / 3;
            // cout << ml << " " << mr << " " << f(ml) << " " << f(mr) << endl;
            if (f(ml) > f(mr))
                l = ml + 1;
            else
                r = mr - 1;
        }
        cout << min(f(l), f(r)) << endl;
    }
    return 0;
}

离线

考虑把询问离线下来排个序就行,单 $\log$ 就做完了。

最后修改:2023 年 12 月 20 日
v我50吃疯狂星期四