详细介绍:【DFS序 异或树状数组】P12385 [蓝桥杯 2023 省 Python B] 异或和|普及+

本文涉及知识点

C++DFS
【C++】树状数组的使用、原理、封装类、样例

P12385 [蓝桥杯 2023 省 Python B] 异或和

题目描述

给一棵含有 n n n 个结点的有根树,根结点为 1 1 1,编号为 i i i 的点有点权 a i a_i ai ( i ∈ [ 1 , n ] ) (i \in [1, n]) (i[1,n])。现在有两种操作,格式如下:

  • 1   x   y 1\ x\ y 1xy 该操作表示将点 x x x 的点权改为 y y y
  • 2   x 2\ x 2x 该操作表示查询以结点 x x x 为根的子树内的所有点的点权的异或和。

现有长度为 m m m 的操作序列,请对于每个第二类操作给出正确的结果。

输入格式

输入的第一行包含两个正整数 n , m n, m n,m,用一个空格分隔。

第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,,an,相邻整数之间使用一个空格分隔。

接下来 n − 1 n-1 n1 行,每行包含两个正整数 u i , v i u_i, v_i ui,vi,表示结点 u i u_i ui v i v_i vi 之间有一条边。

接下来 m m m 行,每行包含一个操作。

输出格式

输出若干行,每行对应一个查询操作的答案。

输入输出样例 #1

输入 #1

4 4
1 2 3 4
1 2
1 3
2 4
2 1
1 1 0
2 1
2 2

输出 #1

4
5
6

说明/提示

评测用例规模与约定

  • 对于 30 % 30\% 30% 的评测用例, n , m ≤ 1000 n, m \leq 1000 n,m1000
  • 对于所有评测用例, 1 ≤ n , m ≤ 100000 1 \leq n, m \leq 100000 1n,m100000 0 ≤ a i , y ≤ 100000 0 \leq a_i, y \leq 100000 0ai,y100000 1 ≤ u i , v i , x ≤ n 1 \leq u_i, v_i, x \leq n 1ui,vi,xn

DFS序 异或树状数组 线段树

操作一:单点修改。 操作二:区间查询
vSort[node] 记录node的DFS序,node子树的DFS序为[vSort[node], vEnd[node])
注意:bit[vSort[i]] = a[i],不是bit[i]=a[i]

代码

核心代码

#include <iostream>
  #include <sstream>
    #include <vector>
      #include<map>
        #include<unordered_map>
          #include<set>
            #include<unordered_set>
              #include<string>
                #include<algorithm>
                  #include<functional>
                    #include<queue>
                      #include <stack>
                        #include<iomanip>
                          #include<numeric>
                            #include <math.h>
                              #include <climits>
                                #include<assert.h>
                                  #include<cstring>
                                    #include<list>
                                      #include<array>
                                        #include <bitset>
                                          using namespace std;
                                          template<
                                          class T1
                                          , class T2
                                          >
                                          std::istream&
                                          operator >>
                                          (std::istream& in, pair<T1, T2>
                                            & pr) {
                                            in >> pr.first >> pr.second;
                                            return in;
                                            }
                                            template<
                                            class T1
                                            , class T2
                                            , class T3
                                            >
                                            std::istream&
                                            operator >>
                                            (std::istream& in, tuple<T1, T2, T3>
                                              & t) {
                                              in >> get<
                                              0>
                                              (t) >> get<
                                              1>
                                              (t) >> get<
                                              2>
                                              (t);
                                              return in;
                                              }
                                              template<
                                              class T1
                                              , class T2
                                              , class T3
                                              , class T4
                                              >
                                              std::istream&
                                              operator >>
                                              (std::istream& in, tuple<T1, T2, T3, T4>
                                                & t) {
                                                in >> get<
                                                0>
                                                (t) >> get<
                                                1>
                                                (t) >> get<
                                                2>
                                                (t) >> get<
                                                3>
                                                (t);
                                                return in;
                                                }
                                                template<
                                                class T1
                                                , class T2
                                                , class T3
                                                , class T4
                                                , class T5
                                                , class T6
                                                , class T7
                                                >
                                                std::istream&
                                                operator >>
                                                (std::istream& in, tuple<T1, T2, T3, T4,T5,T6,T7>
                                                  & t) {
                                                  in >> get<
                                                  0>
                                                  (t) >> get<
                                                  1>
                                                  (t) >> get<
                                                  2>
                                                  (t) >> get<
                                                  3>
                                                  (t) >> get<
                                                  4>
                                                  (t) >> get<
                                                  5>
                                                  (t) >> get<
                                                  6>
                                                  (t);
                                                  return in;
                                                  }
                                                  template<
                                                  class T
                                                  = int>
                                                  vector<T>
                                                    Read() {
                                                    int n;
                                                    cin >> n;
                                                    vector<T>
                                                      ret(n);
                                                      for (int i = 0; i < n; i++) {
                                                      cin >> ret[i];
                                                      }
                                                      return ret;
                                                      }
                                                      template<
                                                      class T
                                                      = int>
                                                      vector<T>
                                                        ReadNotNum() {
                                                        vector<T> ret;
                                                          T tmp;
                                                          while (cin >> tmp) {
                                                          ret.emplace_back(tmp);
                                                          if ('\n' == cin.get()) {
                                                          break;
                                                          }
                                                          }
                                                          return ret;
                                                          }
                                                          template<
                                                          class T
                                                          = int>
                                                          vector<T>
                                                            Read(int n) {
                                                            vector<T>
                                                              ret(n);
                                                              for (int i = 0; i < n; i++) {
                                                              cin >> ret[i];
                                                              }
                                                              return ret;
                                                              }
                                                              template<
                                                              int N = 1'000'000>
                                                              class COutBuff
                                                              {
                                                              public:
                                                              COutBuff() {
                                                              m_p = puffer;
                                                              }
                                                              template<
                                                              class T
                                                              >
                                                              void write(T x) {
                                                              int num[28], sp = 0;
                                                              if (x <
                                                              0)
                                                              *m_p++ = '-', x = -x;
                                                              if (!x)
                                                              *m_p++ = 48;
                                                              while (x)
                                                              num[++sp] = x % 10, x /= 10;
                                                              while (sp)
                                                              *m_p++ = num[sp--] + 48;
                                                              AuotToFile();
                                                              }
                                                              void writestr(const char* sz) {
                                                              strcpy(m_p, sz);
                                                              m_p += strlen(sz);
                                                              AuotToFile();
                                                              }
                                                              inline void write(char ch)
                                                              {
                                                              *m_p++ = ch;
                                                              AuotToFile();
                                                              }
                                                              inline void ToFile() {
                                                              fwrite(puffer, 1, m_p - puffer, stdout);
                                                              m_p = puffer;
                                                              }
                                                              ~COutBuff() {
                                                              ToFile();
                                                              }
                                                              private:
                                                              inline void AuotToFile() {
                                                              if (m_p - puffer > N - 100) {
                                                              ToFile();
                                                              }
                                                              }
                                                              char puffer[N], * m_p;
                                                              };
                                                              template<
                                                              int N = 1'000'000>
                                                              class CInBuff
                                                              {
                                                              public:
                                                              inline CInBuff() {
                                                              }
                                                              inline CInBuff<N>
                                                                &
                                                                operator>>
                                                                (char& ch) {
                                                                FileToBuf();
                                                                while (('\r' == *S) || ('\n' == *S) || (' ' == *S)) { S++;
                                                                }//忽略空格和回车
                                                                ch = *S++;
                                                                return *this;
                                                                }
                                                                inline CInBuff<N>
                                                                  &
                                                                  operator>>
                                                                  (int& val) {
                                                                  FileToBuf();
                                                                  int x(0), f(0);
                                                                  while (!isdigit(*S))
                                                                  f |= (*S++ == '-');
                                                                  while (isdigit(*S))
                                                                  x = (x <<
                                                                  1) + (x <<
                                                                  3) + (*S++ ^ 48);
                                                                  val = f ? -x : x; S++;
                                                                  //忽略空格换行 
                                                                  return *this;
                                                                  }
                                                                  inline CInBuff&
                                                                  operator>>
                                                                  (long long& val) {
                                                                  FileToBuf();
                                                                  long long x(0);
                                                                  int f(0);
                                                                  while (!isdigit(*S))
                                                                  f |= (*S++ == '-');
                                                                  while (isdigit(*S))
                                                                  x = (x <<
                                                                  1) + (x <<
                                                                  3) + (*S++ ^ 48);
                                                                  val = f ? -x : x; S++;
                                                                  //忽略空格换行
                                                                  return *this;
                                                                  }
                                                                  template<
                                                                  class T1
                                                                  , class T2
                                                                  >
                                                                  inline CInBuff&
                                                                  operator>>
                                                                  (pair<T1, T2>
                                                                    & val) {
                                                                    *this >> val.first >> val.second;
                                                                    return *this;
                                                                    }
                                                                    template<
                                                                    class T1
                                                                    , class T2
                                                                    , class T3
                                                                    >
                                                                    inline CInBuff&
                                                                    operator>>
                                                                    (tuple<T1, T2, T3>
                                                                      & val) {
                                                                      *this >> get<
                                                                      0>
                                                                      (val) >> get<
                                                                      1>
                                                                      (val) >> get<
                                                                      2>
                                                                      (val);
                                                                      return *this;
                                                                      }
                                                                      template<
                                                                      class T1
                                                                      , class T2
                                                                      , class T3
                                                                      , class T4
                                                                      >
                                                                      inline CInBuff&
                                                                      operator>>
                                                                      (tuple<T1, T2, T3, T4>
                                                                        & val) {
                                                                        *this >> get<
                                                                        0>
                                                                        (val) >> get<
                                                                        1>
                                                                        (val) >> get<
                                                                        2>
                                                                        (val) >> get<
                                                                        3>
                                                                        (val);
                                                                        return *this;
                                                                        }
                                                                        template<
                                                                        class T
                                                                        = int>
                                                                        inline CInBuff&
                                                                        operator>>
                                                                        (vector<T>
                                                                          & val) {
                                                                          int n;
                                                                          *this >> n;
                                                                          val.resize(n);
                                                                          for (int i = 0; i < n; i++) {
                                                                          *this >> val[i];
                                                                          }
                                                                          return *this;
                                                                          }
                                                                          template<
                                                                          class T
                                                                          = int>
                                                                          vector<T>
                                                                            Read(int n) {
                                                                            vector<T>
                                                                              ret(n);
                                                                              for (int i = 0; i < n; i++) {
                                                                              *this >> ret[i];
                                                                              }
                                                                              return ret;
                                                                              }
                                                                              template<
                                                                              class T
                                                                              = int>
                                                                              vector<T>
                                                                                Read() {
                                                                                vector<T> ret;
                                                                                  *this >> ret;
                                                                                  return ret;
                                                                                  }
                                                                                  private:
                                                                                  inline void FileToBuf() {
                                                                                  const int canRead = m_iWritePos - (S - buffer);
                                                                                  if (canRead >= 100) {
                                                                                  return;
                                                                                  }
                                                                                  if (m_bFinish) {
                                                                                  return;
                                                                                  }
                                                                                  for (int i = 0; i < canRead; i++)
                                                                                  {
                                                                                  buffer[i] = S[i];
                                                                                  //memcpy出错 
                                                                                  }
                                                                                  m_iWritePos = canRead;
                                                                                  buffer[m_iWritePos] = 0;
                                                                                  S = buffer;
                                                                                  int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);
                                                                                  if (readCnt <= 0) { m_bFinish = true;
                                                                                  return;
                                                                                  }
                                                                                  m_iWritePos += readCnt;
                                                                                  buffer[m_iWritePos] = 0;
                                                                                  S = buffer;
                                                                                  }
                                                                                  int m_iWritePos = 0;
                                                                                  bool m_bFinish = false;
                                                                                  char buffer[N + 10], * S = buffer;
                                                                                  };
                                                                                  class CNeiBo
                                                                                  {
                                                                                  public:
                                                                                  static vector<vector<
                                                                                  int>>
                                                                                  Two(int n, const vector<pair<
                                                                                  int, int>>
                                                                                  & edges, bool bDirect, int iBase = 0)
                                                                                  {
                                                                                  vector<vector<
                                                                                  int>>
                                                                                  vNeiBo(n);
                                                                                  for (const auto&
                                                                                  [i1, i2] : edges)
                                                                                  {
                                                                                  vNeiBo[i1 - iBase].emplace_back(i2 - iBase);
                                                                                  if (!bDirect)
                                                                                  {
                                                                                  vNeiBo[i2 - iBase].emplace_back(i1 - iBase);
                                                                                  }
                                                                                  }
                                                                                  return vNeiBo;
                                                                                  }
                                                                                  static vector<vector<
                                                                                  int>>
                                                                                  Two(int n, const vector<vector<
                                                                                  int>>
                                                                                  & edges, bool bDirect, int iBase = 0)
                                                                                  {
                                                                                  vector<vector<
                                                                                  int>>
                                                                                  vNeiBo(n);
                                                                                  for (const auto& v : edges)
                                                                                  {
                                                                                  vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase);
                                                                                  if (!bDirect)
                                                                                  {
                                                                                  vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase);
                                                                                  }
                                                                                  }
                                                                                  return vNeiBo;
                                                                                  }
                                                                                  static vector<vector<std::pair<
                                                                                  int, int>>
                                                                                  >
                                                                                  Three(int n, vector<vector<
                                                                                  int>>
                                                                                  & edges, bool bDirect, int iBase = 0)
                                                                                  {
                                                                                  vector<vector<std::pair<
                                                                                  int, int>>
                                                                                  >
                                                                                  vNeiBo(n);
                                                                                  for (const auto& v : edges)
                                                                                  {
                                                                                  vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase, v[2]);
                                                                                  if (!bDirect)
                                                                                  {
                                                                                  vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase, v[2]);
                                                                                  }
                                                                                  }
                                                                                  return vNeiBo;
                                                                                  }
                                                                                  static vector<vector<std::pair<
                                                                                  int, int>>
                                                                                  >
                                                                                  Three(int n, const vector<tuple<
                                                                                  int, int, int>>
                                                                                  & edges, bool bDirect, int iBase = 0)
                                                                                  {
                                                                                  vector<vector<std::pair<
                                                                                  int, int>>
                                                                                  >
                                                                                  vNeiBo(n);
                                                                                  for (const auto&
                                                                                  [u, v, w] : edges)
                                                                                  {
                                                                                  vNeiBo[u - iBase].emplace_back(v - iBase, w);
                                                                                  if (!bDirect)
                                                                                  {
                                                                                  vNeiBo[v - iBase].emplace_back(u - iBase, w);
                                                                                  }
                                                                                  }
                                                                                  return vNeiBo;
                                                                                  }
                                                                                  static vector<vector<
                                                                                  int>>
                                                                                  Mat(vector<vector<
                                                                                  int>>
                                                                                  & neiBoMat)
                                                                                  {
                                                                                  vector<vector<
                                                                                  int>>
                                                                                  neiBo(neiBoMat.size());
                                                                                  for (int i = 0; i < neiBoMat.size(); i++)
                                                                                  {
                                                                                  for (int j = i + 1; j < neiBoMat.size(); j++)
                                                                                  {
                                                                                  if (neiBoMat[i][j])
                                                                                  {
                                                                                  neiBo[i].emplace_back(j);
                                                                                  neiBo[j].emplace_back(i);
                                                                                  }
                                                                                  }
                                                                                  }
                                                                                  return neiBo;
                                                                                  }
                                                                                  };
                                                                                  template<
                                                                                  class ELE
                                                                                  = int >
                                                                                  class ITreeArrSumOpe
                                                                                  {
                                                                                  public:
                                                                                  virtual void Assign(ELE& dest, const ELE& src) = 0;
                                                                                  virtual ELE Back(const ELE& n1, const ELE& n2) = 0;
                                                                                  };
                                                                                  template<
                                                                                  class ELE
                                                                                  = int >
                                                                                  class CTreeArrAddOpe
                                                                                  :public ITreeArrSumOpe<
                                                                                  ELE>
                                                                                  {
                                                                                  public:
                                                                                  virtual void Assign(ELE& dest, const ELE& src) {
                                                                                  dest += src;
                                                                                  }
                                                                                  virtual ELE Back(const ELE& n1, const ELE& n2) {
                                                                                  return n1 - n2;
                                                                                  }
                                                                                  };
                                                                                  template<
                                                                                  class ELE
                                                                                  = int, class ELEOpe
                                                                                  = CTreeArrAddOpe<ELE>
                                                                                    >
                                                                                    class CTreeArr
                                                                                    {
                                                                                    public:
                                                                                    CTreeArr(int iSize) :m_vData(iSize + 1)
                                                                                    {
                                                                                    }
                                                                                    void Add(int index, ELE value)
                                                                                    {
                                                                                    if ((index <
                                                                                    0) || (index >= m_vData.size() - 1)) {
                                                                                    return;
                                                                                    }
                                                                                    index++;
                                                                                    while (index < m_vData.size())
                                                                                    {
                                                                                    m_ope.Assign(m_vData[index], value);
                                                                                    index += index &
                                                                                    (-index);
                                                                                    }
                                                                                    }
                                                                                    ELE Sum(int index)//[0...index]之和
                                                                                    {
                                                                                    index++;
                                                                                    ELE ret = 0;
                                                                                    while (index)
                                                                                    {
                                                                                    m_ope.Assign(ret, m_vData[index]);
                                                                                    index -= index &
                                                                                    (-index);
                                                                                    }
                                                                                    return ret;
                                                                                    }
                                                                                    ELE Sum() {
                                                                                    return Sum(m_vData.size() - 2);
                                                                                    }
                                                                                    ELE Get(int index)
                                                                                    {
                                                                                    return m_ope.Back(Sum(index), Sum(index - 1));
                                                                                    }
                                                                                    private:
                                                                                    ELEOpe m_ope;
                                                                                    vector<ELE> m_vData;
                                                                                      };
                                                                                      template<
                                                                                      class ELE
                                                                                      = int >
                                                                                      class CTreeArrXorOpe
                                                                                      : public ITreeArrSumOpe <
                                                                                      ELE> {
                                                                                      public:
                                                                                      virtual void Assign(ELE& dest, const ELE& src) {
                                                                                      dest ^= src;
                                                                                      }
                                                                                      virtual ELE Back(const ELE& n1, const ELE& n2) {
                                                                                      return n1 ^ n2;
                                                                                      }
                                                                                      };
                                                                                      template<
                                                                                      class ELE
                                                                                      = int >
                                                                                      class CTreeArrXor
                                                                                      : public CTreeArr<
                                                                                      ELE, CTreeArrXorOpe<
                                                                                      ELE>> {
                                                                                      public:
                                                                                      using CTreeArr<ELE, CTreeArrXorOpe<ELE>>
                                                                                        ::CTreeArr;
                                                                                        };
                                                                                        class Solution
                                                                                        {
                                                                                        public:
                                                                                        vector<
                                                                                        int>
                                                                                        Ans(const int N, vector<
                                                                                        int>
                                                                                        & a, vector<pair<
                                                                                        int, int>> edge, vector<tuple<
                                                                                        int, int, int>>
                                                                                        & ope) {
                                                                                        auto neiBo = CNeiBo::Two(N, edge, false, 1);
                                                                                        int m_iSort = 0;
                                                                                        vector<
                                                                                        int>
                                                                                        vSort(N), vSortEnd(N);
                                                                                        function<
                                                                                        void(int, int)> DFS = [&
                                                                                        ](int cur, int par) {
                                                                                        vSort[cur] = m_iSort++;
                                                                                        for (const auto& next : neiBo[cur]) {
                                                                                        if (next == par) {
                                                                                        continue;
                                                                                        }
                                                                                        DFS(next, cur);
                                                                                        }
                                                                                        vSortEnd[cur] = m_iSort;
                                                                                        };
                                                                                        DFS(0, -1);
                                                                                        CTreeArrXor<
                                                                                        int>
                                                                                        bit(N);
                                                                                        vector<
                                                                                        int>
                                                                                        tmp1(N);
                                                                                        for (int i = 0; i < N; i++) {
                                                                                        bit.Add(vSort[i], a[i]);
                                                                                        tmp1[vSort[i]] = bit.Get(vSort[i]);
                                                                                        }
                                                                                        vector<
                                                                                        int> ans;
                                                                                        for (auto [kind, x, y] : ope) {
                                                                                        x--;
                                                                                        if (1 == kind) {
                                                                                        const int inx = vSort[x];
                                                                                        bit.Add(inx, y ^ bit.Get(inx));
                                                                                        tmp1[inx] = bit.Get(inx);
                                                                                        }
                                                                                        else {
                                                                                        const int cur = bit.Sum(vSortEnd[x] - 1) ^ bit.Sum(vSort[x] - 1);
                                                                                        ans.emplace_back(cur);
                                                                                        }
                                                                                        }
                                                                                        return ans;
                                                                                        }
                                                                                        };
                                                                                        int main() {
                                                                                        #ifdef _DEBUG
                                                                                        freopen("a.in", "r", stdin);
                                                                                        #endif // DEBUG 
                                                                                        ios::sync_with_stdio(0); cin.tie(nullptr);
                                                                                        //CInBuff<> in; COutBuff<10'000'000> ob; 
                                                                                          int N,Q;
                                                                                          cin >> N >> Q;
                                                                                          auto a = Read<
                                                                                          int>
                                                                                          (N );
                                                                                          auto edge = Read<pair<
                                                                                          int,int>>
                                                                                          (N-1);
                                                                                          vector<tuple<
                                                                                          int, int, int>>
                                                                                          ope(Q);
                                                                                          for (int i = 0; i < Q; i++) {
                                                                                          cin >> get<
                                                                                          0>
                                                                                          (ope[i]) >> get<
                                                                                          1>
                                                                                          (ope[i]);
                                                                                          if (1 == get<
                                                                                          0>
                                                                                          (ope[i])) {
                                                                                          cin >> get<
                                                                                          2>
                                                                                          (ope[i]);
                                                                                          }
                                                                                          }
                                                                                          #ifdef _DEBUG 
                                                                                          //printf("N=%d",N);
                                                                                          Out(a, ",a=");
                                                                                          Out(ope, ",ope=");
                                                                                          Out(edge, ",edge=");
                                                                                          /*Out(que, ",que=");*/
                                                                                          //Out(ab, ",ab=");
                                                                                          //Out(par, "par=");
                                                                                          //Out(que, "que=");
                                                                                          //Out(B, "B=");
                                                                                          #endif // DEBUG 
                                                                                          auto res = Solution().Ans(N,a,edge,ope);
                                                                                          for (const auto& i : res)
                                                                                          {
                                                                                          cout << i <<
                                                                                          "\n";
                                                                                          }
                                                                                          return 0;
                                                                                          };

单元测试

vector<
int> a;
vector<pair<
int, int>> edge;
vector<tuple<
int, int, int>> ope;
TEST_METHOD(TestMethod11)
{
a = {
1,2,3,4
}, ope = {
{
2,1,0
},{
1,1,0
},{
2,1,0
},{
2,2,0
}
}, edge = {
{
1,2
},{
1,3
},{
2,4
}
};
auto res = Solution().Ans(a.size(), a, edge, ope);
AssertEx({
4,5,6
}, res);
}

# 扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

posted @ 2025-09-06 18:09  yfceshi  阅读(4)  评论(0)    收藏  举报