单 log 无 LCT 做法……
查看原帖
单 log 无 LCT 做法……
388651
5k_sync_closer楼主2023/2/27 11:27

……而且是目前最优解

先用树剖做法的思路把问题转化成链加单点查,然后不用树剖维护。

我们知道,树上差分可以把链加单点查转化为单点加子树查。

BIT 维护树上差分数组的 DFS 序列即可。

写个 O(n)O(n) 建树,再卡卡常,就最优解了。

#include <cstdio>
#include <algorithm>
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
using namespace std;
char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
inline void R(int &r)
{
    r = 0;
    char c = getchar();
    while (c < '0' || c > '9')
        c = getchar();
    while (c >= '0' && c <= '9')
        r = r * 10 + c - '0', c = getchar();
}
inline void C(char &r)
{
    r = getchar();
    while (r < 'A' || r > 'Z')
        r = getchar();
}
void P(long long x)
{
    if (x >= 10)
        P(x / 10);
    *O++ = x % 10 + '0';
}
struct E
{
    int v, t;
} e[200001];
struct S
{
    char o;
    int x, y;
} q[100001];
int n, m, c, p, a[100001], b[100001], d[100001], f[100001], s[100001], t[100001], h[100001];
inline void A(int u, int v)
{
    e[++c] = {v, h[u]};
    h[u] = c;
}
int F(int x) { return x == f[x] ? x : f[x] = F(f[x]); }
inline void M(int x, int k)
{
    for (x = b[x]; x <= n; x += x & -x)
        t[x] += k;
}
inline int Q(int u)
{
    int q = 0, x = b[u] - 1, y = b[u] + s[u] - 1;
    for (; y > x; y &= y - 1)
        q += t[y];
    for (; x > y; x &= x - 1)
        q -= t[x];
    return q;
}
void D(int u)
{
    s[u] = 1;
    a[b[u] = ++p] = 1;
    for (int i = h[u], v; i; i = e[i].t)
        if (!b[v = e[i].v])
            --a[b[u]], d[v] = u, D(v), s[u] += s[v];
}
int main()
{
    R(n);
    R(m);
    for (int i = 1; i <= n; ++i)
        f[i] = i;
    for (int i = 0, x, y; i < m; ++i)
    {
        C(q[i].o);
        R(q[i].x);
        R(q[i].y);
        x = q[i].x;
        y = q[i].y;
        if (q[i].o == 'A')
            A(x, y), A(y, x);
    }
    for (int i = 1; i <= n; ++i)
        if (!b[i])
            D(i);
    for (int i = 1; i <= n; ++i)
        a[i] += a[i - 1], t[i] = a[i] - a[i & i - 1];
    for (int i = 0, g, x, y, X; i < m; ++i)
    {
        if (d[x = q[i].x] == (y = q[i].y))
            swap(x, y);
        X = F(x);
        g = Q(y);
        if (q[i].o == 'A')
        {
            M(x, g);
            if (d[X])
                M(d[X], -g);
            f[F(y)] = F(x);
        }
        else
            P(1ll * g * (Q(X) - g)), *O++ = '\n';
    }
    return fwrite(obuf, O - obuf, 1, stdout), 0;
}
2023/2/27 11:27
加载中...