3 条题解

  • 0
    @ 2023-2-18 17:22:18

    树链剖分

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 300000 + 5;
    int n;
    vector<int> e[MAXN];
    int a[MAXN];   // 旅行路线
    int ans[MAXN]; // 最终答案
    // 每个点的:父节点、深度、大小、重子节点
    int fa[MAXN], dep[MAXN], siz[MAXN], hson[MAXN];
    void dfs_build(int u, int fat)
    {
        hson[u] = 0;
        siz[u] = 1;
        for (int i = 0; i < e[u].size(); i++)
        {
            int v = e[u][i];
            if (v == fat)
                continue;
            dep[v] = dep[u] + 1;
            fa[v] = u;
            dfs_build(v, u);
            siz[u] += siz[v];
            if (siz[v] > siz[hson[u]])
                hson[u] = v;
        }
    }
    // 每个点的:所在链的链顶、重边优先的 dfs 序、dfs序对应的节点编号
    int tot, top[MAXN], dfn[MAXN], rnk[MAXN];
    void dfs_div(int u, int fa)
    {
        dfn[u] = ++tot;
        rnk[tot] = u;
        if (hson[u])
        {
            top[hson[u]] = top[u];
            dfs_div(hson[u], u);
            for (int i = 0; i < e[u].size(); i++)
            {
                int v = e[u][i];
                if (v == fa || v == hson[u])
                    continue;
                top[v] = v;
                dfs_div(v, u);
            }
        }
    }
    struct SegTree
    {
        int sum[4 * MAXN], lazy[4 * MAXN];
        void up(int now)
        {
            sum[now] = sum[now * 2] + sum[now * 2 + 1];
        }
        void down(int now, int l, int r)
        {
            if (l == r)
                return;
            int mid = (l + r) / 2;
            sum[now * 2] = sum[now * 2] + (mid - l + 1) * lazy[now];
            sum[now * 2 + 1] = sum[now * 2 + 1] + (r - mid) * lazy[now];
            lazy[now * 2] = lazy[now * 2] + lazy[now];
            lazy[now * 2 + 1] = lazy[now * 2 + 1] + lazy[now];
            lazy[now] = 0;
        }
        void build(int now, int l, int r)
        {
            lazy[now] = 0;
            if (l == r)
            {
                sum[now] = 0; //--------
                return;
            }
            int mid = (l + r) / 2;
            build(now * 2, l, mid);
            build(now * 2 + 1, mid + 1, r);
            up(now);
        }
        void add(int now, int l, int r, int x, int y, int z)
        {
            if (x <= l && r <= y)
            {
                sum[now] = sum[now] + (r - l + 1) * z;
                lazy[now] = lazy[now] + z;
                return;
            }
            down(now, l, r);
            int mid = (l + r) / 2;
            if (x <= mid)
                add(now * 2, l, mid, x, y, z);
            if (y >= mid + 1)
                add(now * 2 + 1, mid + 1, r, x, y, z);
            up(now);
        }
        int query(int now, int l, int r, int x, int y)
        {
            if (x <= l && r <= y)
                return sum[now];
            down(now, l, r);
            int mid = (l + r) / 2;
            int res = 0;
            if (x <= mid)
                res = res + query(now * 2, l, mid, x, y);
            if (y >= mid + 1)
                res = res + query(now * 2 + 1, mid + 1, r, x, y);
            return res;
        }
    } st;
    // u~v路径上点都加1
    void update(int u, int v)
    {
        st.add(1, 1, tot, dfn[v], dfn[v], -1);
        int res = 0;
        while (top[u] != top[v])
        {
            if (dep[top[u]] < dep[top[v]])
            {
                // v~top[v] 计入答案中
                st.add(1, 1, tot, dfn[top[v]], dfn[v], 1);
                v = fa[top[v]];
            }
            else
            {
                // u~top[u] 计入答案中
                st.add(1, 1, tot, dfn[top[u]], dfn[u], 1);
                u = fa[top[u]];
            }
        }
        if (dep[u] > dep[v])
            swap(u, v);
        st.add(1, 1, tot, dfn[u], dfn[v], 1);
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        for (int i = 1; i <= n - 1; i++)
        {
            int u, v;
            cin >> u >> v;
            e[u].push_back(v);
            e[v].push_back(u);
        }
        dep[1] = 1;
        fa[1] = 0;
        dfs_build(1, 0);
        tot = 0;
        top[1] = 1;
        dfs_div(1, 0);
        //--------
        st.build(1, 1, tot);
        for (int i = 1; i <= n - 1; i++)
            update(a[i], a[i + 1]);
        for (int i = 1; i <= n; i++)
            cout << st.query(1, 1, tot, dfn[i], dfn[i]) << "\n";
        return 0;
    }
    
    • 0
      @ 2023-2-11 16:20:51

      dfs里面初始化dp

      #include <bits/stdc++.h>
      using namespace std;
      typedef long long ll;
      const int MAXN = 500000;
      int n, m, s;
      vector<int> e[MAXN + 5];
      int dep[MAXN + 5];
      int lg[MAXN + 5];
      int f[MAXN + 5][32];
      void dfs(int u, int fa)
      {
          dep[u] = dep[fa] + 1;
          f[u][0] = fa;
          for (int i = 1; i <= lg[dep[u]]; i++)
              f[u][i] = f[f[u][i - 1]][i - 1];
          for (int i = 0; i < e[u].size(); i++)
          {
              int v = e[u][i];
              if (v == fa)
                  continue;
              dfs(v, u);
          }
      }
      int lca(int x, int y)
      {
          if (dep[x] < dep[y])
              swap(x, y);
          while (dep[x] > dep[y])
              x = f[x][lg[dep[x] - dep[y]] - 1];
          if (x == y)
              return x;
          for (int k = lg[dep[x]] - 1; k >= 0; --k)
              if (f[x][k] != f[y][k])
                  x = f[x][k], y = f[y][k];
          return f[x][0];
      }
      int a[312345];
      int ans[312345];
      void dfs2(int u, int fa)
      {
          for (int i = 0; i < e[u].size(); i++)
          {
              int v = e[u][i];
              if (v == fa)
                  continue;
              dfs2(v, u);
              ans[u] += ans[v];
          }
      }
      int main()
      {
          ios::sync_with_stdio(false);
          cin.tie(0);
          cin >> n;
          for (int i = 1; i <= n; i++)
              cin >> a[i];
          for (int i = 1; i <= n - 1; i++)
          {
              int u, v;
              cin >> u >> v;
              e[u].push_back(v);
              e[v].push_back(u);
          }
          for (int i = 1; i <= n; ++i)
              lg[i] = lg[i - 1] + ((1 << lg[i - 1]) == i);
          dep[0] = 0;
          dfs(1, 0);
          for (int i = 1; i < n; i++)
          {
              int s = a[i];
              int t = a[i + 1];
              int ft = f[a[i + 1]][0];
              int r = lca(s, t);
              int fr = f[lca(s, t)][0];
              if (r != t)
              {
                  ans[s]++;
                  ans[ft]++;
                  ans[r]--;
                  ans[fr]--;
              }
              else
              {
                  ans[s]++;
                  ans[t]--;
              }
          }
          dfs2(1, 0);
          for (int i = 1; i <= n; i++)
              cout << ans[i] << "\n";
          cout << "\n";
          return 0;
      }
      
      • 0
        @ 2023-2-10 16:41:01

        树上差分

        #include <bits/stdc++.h>
        using namespace std;
        typedef long long ll;
        const int MAXN = 500000;
        int n, m, s;
        vector<int> e[MAXN + 5];
        int dep[MAXN + 5];
        int lg[MAXN + 5];
        int f[MAXN + 5][32];
        void dfs(int u, int fa)
        {
            dep[u] = dep[fa] + 1;
            f[u][0] = fa;
            for (int i = 1; i <= lg[dep[u]]; i++)
                f[u][i] = f[f[u][i - 1]][i - 1];
            for (int i = 0; i < e[u].size(); i++)
            {
                int v = e[u][i];
                if (v == fa)
                    continue;
                dfs(v, u);
            }
        }
        int lca(int x, int y)
        {
            if (dep[x] < dep[y])
                swap(x, y);
            while (dep[x] > dep[y])
                x = f[x][lg[dep[x] - dep[y]] - 1];
            if (x == y)
                return x;
            for (int k = lg[dep[x]] - 1; k >= 0; --k)
                if (f[x][k] != f[y][k])
                    x = f[x][k], y = f[y][k];
            return f[x][0];
        }
        int a[312345];
        int ans[312345];
        void dfs2(int u, int fa)
        {
            for (int i = 0; i < e[u].size(); i++)
            {
                int v = e[u][i];
                if (v == fa)
                    continue;
                dfs2(v, u);
                ans[u] += ans[v];
            }
        }
        int main()
        {
            ios::sync_with_stdio(false);
            cin.tie(0);
            cin >> n;
            for (int i = 1; i <= n; i++)
                cin >> a[i];
            for (int i = 1; i <= n - 1; i++)
            {
                int u, v;
                cin >> u >> v;
                e[u].push_back(v);
                e[v].push_back(u);
            }
            for (int i = 1; i <= n; ++i)
                lg[i] = lg[i - 1] + ((1 << lg[i - 1]) == i);
            dep[0] = 0;
            dfs(1, 0);
            for (int i = 1; i < n; i++)
            {
                int s = a[i];
                int t = a[i + 1];
                int ft = f[a[i + 1]][0];
                int r = lca(s, t);
                int fr = f[lca(s, t)][0];
                if (r != t)
                {
                    ans[s]++;
                    ans[ft]++;
                    ans[r]--;
                    ans[fr]--;
                }
                else
                {
                    ans[s]++;
                    ans[t]--;
                }
            }
            dfs2(1, 0);
            for (int i = 1; i <= n; i++)
                cout << ans[i] << "\n";
            cout << "\n";
            return 0;
        }
        
        • 1

        信息

        ID
        60
        时间
        1000ms
        内存
        256MiB
        难度
        5
        标签
        递交数
        56
        已通过
        22
        上传者