2 条题解

  • 0
    @ 2026-9-26 20:45:18

    思路:第一次写dfs序+树状数组。修改某个节点的值将会影响以他根的子树的值。什么是dfs序呢?就是遍历的顺序。我刚开始节点编号可以用来充当dfs序。结果wrong。只能通过dfs来得到dfs序。然后就是差分了。(原理和洛谷 P3368这个题目一样)初始时,每条边都为1.如果u-v为土路,就为1.那么这个时候就让c[v]=1。全部处理完。修改某个点会造成以他为跟的子节点的值发生改变。所以就是一个区间发生了改变。如果根为1,最大叶子节点编号为3.那么这个区间就是【1,3】。怎么来的呢?就是以当前节点的dfs序为左端点,以当前节点为跟能走到最远(或者最大的为右端点)。这样就是区间修改,单点查询了。详细看代码。

    #include<stdio.h>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #define MAXN  250005
    typedef  long long  LL;
    using namespace std;
    
    int n,m,tot;
    vector<int> G[MAXN];
    bool vis[MAXN];
    int Left[MAXN],Right[MAXN];
    int c[MAXN];
    
    int lowbit(int x)
    {
        return (x&((-1)*x));
    }
    
    void add(int x,int d)
    {
        while(x<=n)
        {
            c[x]+=d;
            x+=lowbit(x);
        }
    }
    
    int sum(int x)
    {
        int ans=0;
        while(x>0)
        {
            ans+=c[x];
            x-=lowbit(x);
        }
        return ans;
    }
    
    void dfs(int u,int fa)
    {
        vis[u]=true;
        Left[u]=++tot;
        //tot=u;
        for(int i=0;i<G[u].size();i++)
        {
            int v=G[u][i];
            if(vis[v])
                continue;
            dfs(v,u);
        }
        Right[u]=tot;
    }
    
    int main()
    {
        scanf("%d",&n);
        tot=0;
        int uu,vv;
        for(int i=1;i<n;i++)
        {
            scanf("%d %d",&uu,&vv);
            G[uu].push_back(vv);
            G[vv].push_back(uu);
        }
        memset(vis,false,sizeof(vis));
        dfs(1,-1);
        for(int i=2;i<=n;i++)
        {
            add(Left[i],1);
            add(Right[i]+1,-1);
        }
        scanf("%d",&m);
        int mm,nn;
        char ch;
        for(int i=0;i<n+m-1;i++)
        {
            cin>>ch;
            if(ch=='W')
            {
                cin>>mm;
                printf("%d\n",sum(Left[mm]));
            }
            else if(ch=='A')
            {
               cin>>mm>>nn;
                add(Left[nn],-1);
                add(Right[nn]+1,1);
            }
            //getchar();
        }
        return 0;
    }
    
    
    • 0
      @ 2025-10-8 17:02:57
      #include <bits/stdc++.h>
      using namespace std;
      const int N = 250010;
      int n, c[N];
      inline void add(int x, int k) { for (; x <= n; x += (x & -x)) c[x] += k; }
      inline int getsum(int x) { int res = 0; for (; x; x -= (x & -x)) res += c[x]; return res; }
      vector<int> G[N];
      int l[N], r[N], tsp;
      // l[i], r[i]分别表示以i为根节点的子树在dfs序中的最左位置和最右位置
      void dfs(int x, int xfa)
      {
          l[x] = ++tsp;
          for (int y : G[x]) if (y != xfa) dfs(y, x);
          r[x] = tsp;
      }
      
      int main()
      {
          scanf("%d", &n);
          for (int i = 1, x, y; i < n; i++) { scanf("%d%d", &x, &y); G[x].push_back(y); G[y].push_back(x); }
          tsp = 0; dfs(1, 0);
          memset(c, 0, sizeof(c));
          for (int i = 2; i <= n; i++)
              add(l[i], 1),
              add(r[i] + 1, -1);
      
          int m; scanf("%d", &m);
          for (int i = 1; i <= m + n - 1; i++)
          {
              char c[2]; scanf("%s", c);
              if (c[0] == 'W')
              {
                  int x; scanf("%d", &x);
                  printf("%d\n", getsum(l[x]));
              }
              else
              {
                  int x, y; scanf("%d%d", &x, &y);
                  if (l[x] > l[y]) swap(x, y);
                  add(l[y], -1);
                  add(r[y] + 1, 1);
              }
          }
          return 0;
      }
      
      • 1

      信息

      ID
      2756
      时间
      2000ms
      内存
      64MiB
      难度
      7
      标签
      递交数
      17
      已通过
      9
      上传者