P4093:「HEOI2016/TJOI2016」序列 – 题解

主要思路

大概就是要求一个子序列,使得在所有变化中始终长度最长。我们可以考虑分治,讨论变化的点的左右位置,然后用树状数组维护一下即可。

代码

// P4093.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 1e5 + 200;

int n, m, ai[MAX_N], mx[MAX_N], mn[MAX_N], dp[MAX_N], nodes[MAX_N], idx[MAX_N];

inline int lowbit(int x) { return x & (-x); }

void update(int x, int d)
{
    for (; x <= n; x += lowbit(x))
        nodes[x] = max(nodes[x], d);
}

void clear(int x)
{
    for (; x <= n; x += lowbit(x))
        nodes[x] = 0;
}

int query(int x, int ret = 0)
{
    for (; x; x -= lowbit(x))
        ret = max(ret, nodes[x]);
    return ret;
}

void solve(int l, int r)
{
    if (l == r)
        return (void)(dp[l] = max(dp[l], 1));
    int mid = (l + r) >> 1;
    solve(l, mid);
    for (int i = l; i <= r; i++)
        idx[i] = i;
    sort(idx + l, idx + mid + 1, [](const int &a, const int &b) { return mx[a] < mx[b]; });
    sort(idx + mid + 1, idx + r + 1, [](const int &a, const int &b) { return ai[a] < ai[b]; });
    for (int i = mid + 1, ptr = l; i <= r; i++)
    {
        while (ptr <= mid && mx[idx[ptr]] <= ai[idx[i]])
            update(ai[idx[ptr]], dp[idx[ptr]]), ptr++;
        dp[idx[i]] = max(dp[idx[i]], query(mn[idx[i]]) + 1);
    }
    for (int i = mid + 1, ptr = l; i <= r; i++)
        while (ptr <= mid && mx[idx[ptr]] <= ai[idx[i]])
            clear(ai[idx[ptr]]), ptr++;
    solve(mid + 1, r);
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%d", &ai[i]), mx[i] = mn[i] = ai[i];
    for (int i = 1, x, y; i <= n; i++)
        scanf("%d%d", &x, &y), mx[x] = max(mx[x], y), mn[x] = min(mn[x], y);
    solve(1, n);
    int ans = *max_element(dp + 1, dp + 1 + n);
    printf("%d\n", ans);
    return 0;
}

 

BZOJ5093:「Lydsy1711月赛」图的价值 – 题解

主要思路

算是个简单题吧。

首先列个暴力式子:

\[ \sum_G \sum_{i = 1}^n d_i^k \]

发现很不现实。我们考虑把点拆开来考虑,因为全集里面可以直接独立的来算。考虑某个点度数为 \(x\) 的方案数,就变成了:

\[ n \sum_{x = 0}^{n – 1} x^k f(x) \]

其中 \(f(x)\) 代表的是一个图某个点的度数为 \(x\) 的方案数。其实稍微思考下就知道,我们可以把这个点剥离出来,强制连边之后再生成一个图即可:

\[ \begin{aligned} f(x) &= {n – 1 \choose x} 2^{n – 1 \choose 2} \\ ans &= n \sum_{x = 0}^{n – 1} x^k {n – 1 \choose x} 2^{n – 1 \choose 2} \\ &= n2^{n – 1 \choose 2} \sum_{x = 0}^{n – 1} x^k {n – 1 \choose x} \end{aligned} \]

Continue reading →

P4380:「USACO18OPEN」Multiplayer Moo S – 题解

主要思路

这个题有点 nb。

按道理来讲直接做第二问得要 \(\Theta(n^4)\) 的时间,而且看上去也没有什么搞头。我们考虑处理出所有的接壤位置 \( (x, y, c_a, c_y) \) 代表颜色为 \(c_x\) 、编号 \(x\) 的点和颜色为 \(c_y\) 、编号 \(y\) 的点接壤。这样的接壤位置只有 \(\Theta(n^2)\) 个,所以我们分类出来之后再用并查集搞即可。

Continue reading →

Codeforces 704D:Captain America – 题解

主要思路

一道比较板的上下界网络流。先考虑 \( red > blue \) 的情况,我们把所有点染成红色的然后再做个最大替换即可。我们考虑对每个点、每个横坐标、每个纵坐标做一个点,横坐标和源点、纵坐标和汇点的边需要大概算一下,得出流量范围 \(\frac{cnt_x}{2} \leq flow \leq \frac{d + cnt_x}{2}\)。得出这个范围之后就用板子套一下即可。

Continue reading →