【线段树 二分查找】P3939 数颜色|遍及+

打印 上一主题 下一主题

主题 1046|帖子 1046|积分 3138

本文涉及知识点

C++线段树
C++二分查找
P3939 数颜色

题目配景

大样例可在页面底部「附件」中下载。
题目描述

小 C 的兔子不是雪白的,而是五彩缤纷的。每只兔子都有一种颜色,差异的兔子可能有 相同的颜色。小 C 把她标号从 1 到                                    n                              n                  n 的                                    n                              n                  n 只兔子排成长长的一排,来给他们喂胡萝卜吃。 排列完成后,第                                    i                              i                  i 只兔子的颜色是                                              a                            i                                       a_i                  ai​。
俗话说得好,“萝卜青菜,各有所爱”。小 C 发现,差异颜色的兔子可能有对胡萝卜的 差异偏好。好比,银色的兔子最喜好吃金色的胡萝卜,金色的兔子更喜好吃胡萝卜叶子,而 绿色的兔子却喜好吃酸一点的胡萝卜……为了满足兔子们的要求,小 C 非常苦恼。所以,为 了使得胡萝卜喂得更加准确,小 C 想知道在区间                                    [                                   l                            j                                  ,                                   r                            j                                  ]                              [l_j,r_j]                  [lj​,rj​] 里有多少只颜色为                                              c                            j                                       c_j                  cj​ 的兔子。
不过,因为小 C 的兔子们都非常地活泼,它们不是很愿意待在一个固定的位置;与此同 时,小 C 也在根据她知道的信息来给兔子们调解位置。所以,偶然编号为                                              x                            j                                       x_j                  xj​ 和                                              x                            j                                  +                         1                              x_j+1                  xj​+1 的两 只兔子会互换位置。 小 C 被这一系列贫苦事给难住了。你能帮帮她吗?
输入格式

从标准输入中读入数据。 输入第 1 行两个正整数                                    n                              n                  n,                                   m                              m                  m。
输入第 2 行                                    n                              n                  n 个正整数,第                                    i                              i                  i 个数体现第                                    i                              i                  i 只兔子的颜色                                              a                            i                                       a_i                  ai​。
输入接下来                                    m                              m                  m 行,每行为以下两种中的一种:


  • “                                             1                                                                           l                                  j                                                                                      r                                  j                                                                                      c                                  j                                                 1\ l_j\ r_j\ c_j                        1 lj​ rj​ cj​” :扣问在区间                                              [                                           l                                  j                                          ,                                           r                                  j                                          ]                                      [l_j,r_j]                        [lj​,rj​] 里有多少只颜色为                                                          c                                  j                                                 c_j                        cj​ 的兔子;
  • “                                             2                                                                           x                                  j                                                 2\ x_j                        2 xj​”:                                                          x                                  j                                                 x_j                        xj​ 和                                                          x                                  j                                          +                               1                                      x_j+1                        xj​+1 两只兔子互换了位置。
输特别式

输出到标准输出中。
对于每个 1 操作,输出一行一个正整数,体现你对于这个扣问的答案。
输入输出样例 #1

输入 #1

  1. 6 5
  2. 1 2 3 2 3 3  
  3. 1 1 3 2
  4. 1 4 6 3  
  5. 2 3
  6. 1 1 3 2  
  7. 1 4 6 3
复制代码
输出 #1

  1. 1
  2. 2
  3. 2
  4. 3
复制代码
阐明/提示

【样例 1 阐明】
前两个 1 操作和后两个 1 操作对应相同;在第三次的 2 操作后,3 号兔子和 4 号兔子
互换了位置,序列变为 1
2
2
3
3 3。
【数据范围与约定】
子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解 决一部分测试数据。 对于所有测试点,有                                    1                         ≤                                   l                            j                                  <                                   r                            j                                  ≤                         n                         ,                         1                         ≤                                   x                            j                                  <                         n                              1 \le l_j < r_j \le n,1 \le x_j < n                  1≤lj​<rj​≤n,1≤xj​<n。 每个测试点的数据规模及特点如下表:

特殊性子 1:包管对于所有操作 1,有                                    ∣                                   r                            j                                  −                                   l                            j                                  ∣                         ≤                         20                              |r_j - l_j| \le 20                  ∣rj​−lj​∣≤20 或                                    ∣                                   r                            j                                  −                                   l                            j                                  ∣                         ≤                         n                         −                         20                              |r_j - l_j| \le n - 20                  ∣rj​−lj​∣≤n−20。
特殊性子 2:包管不会有两只相同颜色的兔子。
P3939 数颜色

令颜色的最大值是MC,则每种颜色开一棵线段树,单点更新,动态开点。求和,如果此树是当前颜色,为1,否则为0。
空间复杂度:O(MC+N+M)。不能静态开点,否则内存超限。
代码

焦点代码(卡常)

最后几个用例超内存
  1. #include <iostream>
  2. #include <sstream>
  3. #include <vector>
  4. #include<map>
  5. #include<unordered_map>
  6. #include<set>
  7. #include<unordered_set>
  8. #include<string>
  9. #include<algorithm>
  10. #include<functional>
  11. #include<queue>
  12. #include <stack>
  13. #include<iomanip>
  14. #include<numeric>
  15. #include <math.h>
  16. #include <climits>
  17. #include<assert.h>
  18. #include<cstring>
  19. #include<list>
  20. #include <bitset>
  21. using namespace std;
  22. template<class T1, class T2>
  23. std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {
  24.         in >> pr.first >> pr.second;
  25.         return in;
  26. }
  27. template<class T1, class T2, class T3 >
  28. std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {
  29.         in >> get<0>(t) >> get<1>(t) >> get<2>(t);
  30.         return in;
  31. }
  32. template<class T1, class T2, class T3, class T4 >
  33. std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {
  34.         in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);
  35.         return in;
  36. }
  37. template<class T = int>
  38. vector<T> Read() {
  39.         int n;
  40.         scanf("%d", &n);
  41.         vector<T> ret(n);
  42.         for (int i = 0; i < n; i++) {
  43.                 cin >> ret[i];
  44.         }
  45.         return ret;
  46. }
  47. template<class T = int>
  48. vector<T> Read(int n) {
  49.         vector<T> ret(n);
  50.         for (int i = 0; i < n; i++) {
  51.                 cin >> ret[i];
  52.         }
  53.         return ret;
  54. }
  55. template<int N = 12 * 1'000'000>
  56. class COutBuff
  57. {
  58. public:
  59.         COutBuff() {
  60.                 m_p = puffer;
  61.         }
  62.         template<class T>
  63.         void write(T x) {
  64.                 int num[28], sp = 0;
  65.                 if (x < 0)
  66.                         *m_p++ = '-', x = -x;
  67.                 if (!x)
  68.                         *m_p++ = 48;
  69.                 while (x)
  70.                         num[++sp] = x % 10, x /= 10;
  71.                 while (sp)
  72.                         *m_p++ = num[sp--] + 48;
  73.         }
  74.         inline void write(char ch)
  75.         {
  76.                 *m_p++ = ch;
  77.         }
  78.         inline void ToFile() {
  79.                 fwrite(puffer, 1, m_p - puffer, stdout);
  80.         }
  81. private:
  82.         char  puffer[N], * m_p;
  83. };
  84. template<int N = 12 * 1'000'000>
  85. class CInBuff
  86. {
  87. public:
  88.         inline CInBuff() {
  89.                 fread(buffer, 1, N, stdin);
  90.         }
  91.         inline int Read() {
  92.                 int x(0), f(0);
  93.                 while (!isdigit(*S))
  94.                         f |= (*S++ == '-');
  95.                 while (isdigit(*S))
  96.                         x = (x << 1) + (x << 3) + (*S++ ^ 48);
  97.                 return f ? -x : x;
  98.         }
  99. private:
  100.         char buffer[N], * S = buffer;
  101. };
  102. template<class TSave, class TRecord >
  103. class CSingeUpdateLineTree
  104. {
  105. protected:
  106.         virtual void OnInit(TSave& save, int iSave) = 0;
  107.         virtual void OnQuery(TSave& ans, const TSave& cur) = 0;
  108.         virtual void OnUpdate(TSave& save, int iSave, const TRecord& update) = 0;
  109.         virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) = 0;
  110. };
  111. template<class TSave, class TRecord >
  112. class CVectorSingUpdateLineTree : public CSingeUpdateLineTree<TSave, TRecord>
  113. {
  114. public:
  115.         CVectorSingUpdateLineTree(int iEleSize, TSave tDefault) :m_iEleSize(iEleSize), m_save(iEleSize * 4, tDefault), m_tDefault(tDefault) {
  116.         }
  117.         void Update(int index, TRecord update) {
  118.                 Update(1, 0, m_iEleSize - 1, index, update);
  119.         }
  120.         TSave Query(int leftIndex, int leftRight) {
  121.                 TSave ans;
  122.                 Query(1, 0, m_iEleSize - 1, leftIndex, leftRight);
  123.                 return ans;
  124.         }
  125.         void Init() {
  126.                 Init(1, 0, m_iEleSize - 1);
  127.         }
  128.         TSave QueryAll() {
  129.                 return m_save[1];
  130.         }
  131. protected:
  132.         int m_iEleSize;
  133.         void Init(int iNodeNO, int iSaveLeft, int iSaveRight)
  134.         {
  135.                 if (iSaveLeft == iSaveRight) {
  136.                         this->OnInit(m_save[iNodeNO], iSaveLeft);
  137.                         return;
  138.                 }
  139.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  140.                 Init(iNodeNO * 2, iSaveLeft, mid);
  141.                 Init(iNodeNO * 2 + 1, mid + 1, iSaveRight);
  142.                 this->OnUpdateParent(m_save[iNodeNO], m_save[iNodeNO * 2], m_save[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);
  143.         }
  144.         void Query(TSave& ans, int iNodeNO, int iSaveLeft, int iSaveRight, int iQueryLeft, int iQueryRight) {
  145.                 if ((iSaveLeft >= iQueryLeft) && (iSaveRight <= iQueryRight)) {
  146.                         this->OnQuery(ans, m_save[iNodeNO]);
  147.                         return;
  148.                 }
  149.                 if (iSaveLeft == iSaveRight) {//没有子节点
  150.                         return;
  151.                 }
  152.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  153.                 if (mid >= iQueryLeft) {
  154.                         Query(iNodeNO * 2, iSaveLeft, mid, iQueryLeft, iQueryRight);
  155.                 }
  156.                 if (mid + 1 <= iQueryRight) {
  157.                         Query(iNodeNO * 2 + 1, mid + 1, iSaveRight, iQueryLeft, iQueryRight);
  158.                 }
  159.         }
  160.         void Update(int iNodeNO, int iSaveLeft, int iSaveRight, int iUpdateNO, TRecord update) {
  161.                 if (iSaveLeft == iSaveRight)
  162.                 {
  163.                         this->OnUpdate(m_save[iNodeNO], iSaveLeft, update);
  164.                         return;
  165.                 }
  166.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  167.                 if (iUpdateNO <= mid) {
  168.                         Update(iNodeNO * 2, iSaveLeft, mid, iUpdateNO, update);
  169.                 }
  170.                 else {
  171.                         Update(iNodeNO * 2 + 1, mid + 1, iSaveRight, iUpdateNO, update);
  172.                 }
  173.                 this->OnUpdateParent(m_save[iNodeNO], m_save[iNodeNO * 2], m_save[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);
  174.         }
  175.         vector<TSave> m_save;
  176.         const TSave m_tDefault;
  177. };
  178. template<class TSave, class TRecord >
  179. class CTreeSingeLineTree : public CSingeUpdateLineTree<TSave, TRecord>
  180. {
  181. protected:
  182.         struct CTreeNode
  183.         {
  184.                 int Cnt()const { return m_iMaxIndex - m_iMinIndex + 1; }
  185.                 int m_iMinIndex;
  186.                 int m_iMaxIndex;
  187.                 TSave data;
  188.                 CTreeNode* m_lChild = nullptr, * m_rChild = nullptr;
  189.         };
  190.         CTreeNode* m_root;
  191.         TSave m_tDefault;
  192. public:
  193.         CTreeSingeLineTree(int iMinIndex, int iMaxIndex, TSave tDefault) {
  194.                 m_tDefault = tDefault;
  195.                 m_root = CreateNode(iMinIndex, iMaxIndex);
  196.         }
  197.         void Init() {
  198.                 Init(m_root);
  199.         }
  200.         void Update(int index, TRecord update) {
  201.                 Update(m_root, index, update);
  202.         }
  203.         TSave QueryAll() {
  204.                 return m_root->data;
  205.         }
  206.         TSave Query(int leftIndex, int leftRight) {
  207.                 TSave ans = m_tDefault;
  208.                 Query(ans, m_root, leftIndex, leftRight);
  209.                 return ans;
  210.         }
  211. protected:
  212.         void Query(TSave& ans, CTreeNode* node, int iQueryLeft, int iQueryRight) {
  213.                 if ((node->m_iMinIndex >= iQueryLeft) && (node->m_iMaxIndex <= iQueryRight)) {
  214.                         this->OnQuery(ans, node->data);
  215.                         return;
  216.                 }
  217.                 if (1 == node->Cnt()) {//没有子节点
  218.                         return;
  219.                 }
  220.                 CreateChilds(node);
  221.                 const int mid = node->m_iMinIndex + (node->m_iMaxIndex - node->m_iMinIndex) / 2;
  222.                 if (mid >= iQueryLeft) {
  223.                         Query(ans, node->m_lChild, iQueryLeft, iQueryRight);
  224.                 }
  225.                 if (mid + 1 <= iQueryRight) {
  226.                         Query(ans, node->m_rChild, iQueryLeft, iQueryRight);
  227.                 }
  228.         }
  229.         void Init(CTreeNode* node)
  230.         {
  231.                 if (1 == node->Cnt()) {
  232.                         this->OnInit(node->data, node->m_iMinIndex);
  233.                         return;
  234.                 }
  235.                 CreateChilds(node);
  236.                 Init(node->m_lChild);
  237.                 Init(node->m_rChild);
  238.                 this->OnUpdateParent(node->data, node->m_lChild->data, node->m_rChild->data, node->m_iMinIndex, node->m_iMaxIndex);
  239.         }
  240.         void Update(CTreeNode* node, int iUpdateNO, TRecord update) {
  241.                 if ((iUpdateNO < node->m_iMinIndex) || (iUpdateNO > node->m_iMaxIndex)) {
  242.                         return;
  243.                 }
  244.                 if (1 == node->Cnt()) {
  245.                         this->OnUpdate(node->data, node->m_iMinIndex, update);
  246.                         return;
  247.                 }
  248.                 CreateChilds(node);
  249.                 Update(node->m_lChild, iUpdateNO, update);
  250.                 Update(node->m_rChild, iUpdateNO, update);
  251.                 this->OnUpdateParent(node->data, node->m_lChild->data, node->m_rChild->data, node->m_iMinIndex, node->m_iMaxIndex);
  252.         }
  253.         void CreateChilds(CTreeNode* node) {
  254.                 if (nullptr != node->m_lChild) { return; }
  255.                 const int iSaveLeft = node->m_iMinIndex;
  256.                 const int iSaveRight = node->m_iMaxIndex;
  257.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  258.                 node->m_lChild = CreateNode(iSaveLeft, mid);
  259.                 node->m_rChild = CreateNode(mid + 1, iSaveRight);
  260.         }
  261.         CTreeNode* CreateNode(int iMinIndex, int iMaxIndex) {
  262.                 CTreeNode* node = new CTreeNode;
  263.                 node->m_iMinIndex = iMinIndex;
  264.                 node->m_iMaxIndex = iMaxIndex;
  265.                 node->data = m_tDefault;
  266.                 return node;
  267.         }
  268. };
  269. typedef int TSave;
  270. typedef int  TRecord;
  271. class  CMyLineTree : public  CTreeSingeLineTree<TSave, TRecord>
  272. {
  273. public:
  274.         using CTreeSingeLineTree<TSave, TRecord>::CTreeSingeLineTree;
  275. protected:
  276.         virtual void OnInit(TSave& save, int iSave) {}
  277.         virtual void OnQuery(TSave& ans, const TSave& cur) {
  278.                 ans += cur;
  279.         }
  280.         virtual void OnUpdate(TSave& save, int iSave, const TRecord& update) {
  281.                 save += update;
  282.         }
  283.         virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) {
  284.                 par = left + r;
  285.         }
  286. };
  287. class Solution {
  288. public:
  289.         vector<int> Ans(vector<int>& a, vector<tuple<int, int, int>>& que) {
  290.                 const int N = a.size();
  291.                 int M = *max_element(a.begin(), a.end());
  292.                 vector<CMyLineTree*> lineTrees;
  293.                 for (int i = 0; i <= M; i++) {
  294.                         lineTrees.emplace_back(new CMyLineTree(1, N, 0));
  295.                 }
  296.                 for (int i = 1; i <= N; i++) {
  297.                         lineTrees[a[i - 1]]->Update(i, 1);
  298.                 }
  299.                 vector<int> ans;
  300.                 for (const auto& [left, r, c] : que) {
  301.                         if (0 != r) {
  302.                                 if (c > M) {
  303.                                         ans.emplace_back(0);
  304.                                 }
  305.                                 else {
  306.                                         ans.emplace_back(lineTrees[c]->Query(left, r));
  307.                                 }                               
  308.                         }
  309.                         else {
  310.                                 lineTrees[a[left - 1]]->Update(left, -1);
  311.                                 lineTrees[a[left]]->Update(left + 1, -1);
  312.                                 swap(a[left - 1], a[left]);
  313.                                 lineTrees[a[left - 1]]->Update(left, 1);
  314.                                 lineTrees[a[left]]->Update(left + 1, 1);
  315.                         }
  316.                 }
  317.                 return ans;
  318.         }
  319. };
  320. int main() {       
  321. #ifdef _DEBUG
  322.         freopen("a.in", "r", stdin);
  323. #endif // DEBUG               
  324.         int n,q;
  325.         cin >> n >> q;
  326.         auto a = Read<int>(n);
  327.         vector<tuple<int, int, int>> que(q);
  328.                 int kind;
  329.                 for (int i = 0; i < q; i++) {
  330.                         cin >> kind >> get<0>(que[i]) ;
  331.                         if (1 == kind) {
  332.                                 cin >> get<1>(que[i]) >> get<2>(que[i]);
  333.                         }
  334.                 }
  335. #ifdef _DEBUG               
  336.                 /*printf("T=%d,", T);*/
  337.                 /*Out(a, "a=");
  338.                 Out(que, "que=");*/
  339. #endif // DEBUG       
  340.                 auto res = Solution().Ans(a,que);
  341.                 for (const auto& i : res)
  342.                 {
  343.                         cout << i << endl;
  344.                 }
  345.         return 0;
  346. }
复制代码
优化

修改模板,断送简洁性或通用性来提升性子。作为工程师很反感。如果某个颜色没被查询,则不为此颜色建树。一种颜色最后一次查询时,delete。此方法不可行,还是内存超限。
  1. #include <iostream>
  2. #include <sstream>
  3. #include <vector>
  4. #include<map>
  5. #include<unordered_map>
  6. #include<set>
  7. #include<unordered_set>
  8. #include<string>
  9. #include<algorithm>
  10. #include<functional>
  11. #include<queue>
  12. #include <stack>
  13. #include<iomanip>
  14. #include<numeric>
  15. #include <math.h>
  16. #include <climits>
  17. #include<assert.h>
  18. #include<cstring>
  19. #include<list>
  20. #include <bitset>
  21. using namespace std;
  22. template<class T1, class T2>
  23. std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {
  24.         in >> pr.first >> pr.second;
  25.         return in;
  26. }
  27. template<class T1, class T2, class T3 >
  28. std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {
  29.         in >> get<0>(t) >> get<1>(t) >> get<2>(t);
  30.         return in;
  31. }
  32. template<class T1, class T2, class T3, class T4 >
  33. std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {
  34.         in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);
  35.         return in;
  36. }
  37. template<class T = int>
  38. vector<T> Read() {
  39.         int n;
  40.         scanf("%d", &n);
  41.         vector<T> ret(n);
  42.         for (int i = 0; i < n; i++) {
  43.                 cin >> ret[i];
  44.         }
  45.         return ret;
  46. }
  47. template<class T = int>
  48. vector<T> Read(int n) {
  49.         vector<T> ret(n);
  50.         for (int i = 0; i < n; i++) {
  51.                 cin >> ret[i];
  52.         }
  53.         return ret;
  54. }
  55. template<int N = 12 * 1'000'000>
  56. class COutBuff
  57. {
  58. public:
  59.         COutBuff() {
  60.                 m_p = puffer;
  61.         }
  62.         template<class T>
  63.         void write(T x) {
  64.                 int num[28], sp = 0;
  65.                 if (x < 0)
  66.                         *m_p++ = '-', x = -x;
  67.                 if (!x)
  68.                         *m_p++ = 48;
  69.                 while (x)
  70.                         num[++sp] = x % 10, x /= 10;
  71.                 while (sp)
  72.                         *m_p++ = num[sp--] + 48;
  73.         }
  74.         inline void write(char ch)
  75.         {
  76.                 *m_p++ = ch;
  77.         }
  78.         inline void ToFile() {
  79.                 fwrite(puffer, 1, m_p - puffer, stdout);
  80.         }
  81. private:
  82.         char  puffer[N], * m_p;
  83. };
  84. template<int N = 12 * 1'000'000>
  85. class CInBuff
  86. {
  87. public:
  88.         inline CInBuff() {
  89.                 fread(buffer, 1, N, stdin);
  90.         }
  91.         inline int Read() {
  92.                 int x(0), f(0);
  93.                 while (!isdigit(*S))
  94.                         f |= (*S++ == '-');
  95.                 while (isdigit(*S))
  96.                         x = (x << 1) + (x << 3) + (*S++ ^ 48);
  97.                 return f ? -x : x;
  98.         }
  99. private:
  100.         char buffer[N], * S = buffer;
  101. };
  102. template<class TSave, class TRecord >
  103. class CSingeUpdateLineTree
  104. {
  105. protected:
  106.         virtual void OnInit(TSave& save, int iSave) = 0;
  107.         virtual void OnQuery(TSave& ans, const TSave& cur) = 0;
  108.         virtual void OnUpdate(TSave& save, int iSave, const TRecord& update) = 0;
  109.         virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) = 0;
  110. };
  111. template<class TSave, class TRecord >
  112. class CVectorSingUpdateLineTree : public CSingeUpdateLineTree<TSave, TRecord>
  113. {
  114. public:
  115.         CVectorSingUpdateLineTree(int iEleSize, TSave tDefault) :m_iEleSize(iEleSize), m_save(iEleSize * 4, tDefault), m_tDefault(tDefault) {
  116.         }
  117.         void Update(int index, TRecord update) {
  118.                 Update(1, 0, m_iEleSize - 1, index, update);
  119.         }
  120.         TSave Query(int leftIndex, int leftRight) {
  121.                 TSave ans;
  122.                 Query(1, 0, m_iEleSize - 1, leftIndex, leftRight);
  123.                 return ans;
  124.         }
  125.         void Init() {
  126.                 Init(1, 0, m_iEleSize - 1);
  127.         }
  128.         TSave QueryAll() {
  129.                 return m_save[1];
  130.         }
  131. protected:
  132.         int m_iEleSize;
  133.         void Init(int iNodeNO, int iSaveLeft, int iSaveRight)
  134.         {
  135.                 if (iSaveLeft == iSaveRight) {
  136.                         this->OnInit(m_save[iNodeNO], iSaveLeft);
  137.                         return;
  138.                 }
  139.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  140.                 Init(iNodeNO * 2, iSaveLeft, mid);
  141.                 Init(iNodeNO * 2 + 1, mid + 1, iSaveRight);
  142.                 this->OnUpdateParent(m_save[iNodeNO], m_save[iNodeNO * 2], m_save[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);
  143.         }
  144.         void Query(TSave& ans, int iNodeNO, int iSaveLeft, int iSaveRight, int iQueryLeft, int iQueryRight) {
  145.                 if ((iSaveLeft >= iQueryLeft) && (iSaveRight <= iQueryRight)) {
  146.                         this->OnQuery(ans, m_save[iNodeNO]);
  147.                         return;
  148.                 }
  149.                 if (iSaveLeft == iSaveRight) {//没有子节点
  150.                         return;
  151.                 }
  152.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  153.                 if (mid >= iQueryLeft) {
  154.                         Query(iNodeNO * 2, iSaveLeft, mid, iQueryLeft, iQueryRight);
  155.                 }
  156.                 if (mid + 1 <= iQueryRight) {
  157.                         Query(iNodeNO * 2 + 1, mid + 1, iSaveRight, iQueryLeft, iQueryRight);
  158.                 }
  159.         }
  160.         void Update(int iNodeNO, int iSaveLeft, int iSaveRight, int iUpdateNO, TRecord update) {
  161.                 if (iSaveLeft == iSaveRight)
  162.                 {
  163.                         this->OnUpdate(m_save[iNodeNO], iSaveLeft, update);
  164.                         return;
  165.                 }
  166.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  167.                 if (iUpdateNO <= mid) {
  168.                         Update(iNodeNO * 2, iSaveLeft, mid, iUpdateNO, update);
  169.                 }
  170.                 else {
  171.                         Update(iNodeNO * 2 + 1, mid + 1, iSaveRight, iUpdateNO, update);
  172.                 }
  173.                 this->OnUpdateParent(m_save[iNodeNO], m_save[iNodeNO * 2], m_save[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);
  174.         }
  175.         vector<TSave> m_save;
  176.         const TSave m_tDefault;
  177. };
  178. template<class TSave, class TRecord >
  179. class CTreeSingeLineTree : public CSingeUpdateLineTree<TSave, TRecord>
  180. {
  181. protected:
  182.         struct CTreeNode
  183.         {
  184.                 int Cnt()const { return m_iMaxIndex - m_iMinIndex + 1; }
  185.                 int m_iMinIndex;
  186.                 int m_iMaxIndex;
  187.                 TSave data;
  188.                 CTreeNode* m_lChild = nullptr, * m_rChild = nullptr;
  189.                 ~CTreeNode() {
  190.                         delete m_lChild; m_lChild = nullptr;
  191.                         delete m_rChild; m_rChild = nullptr;
  192.                 }
  193.         };
  194.         CTreeNode* m_root;
  195.         TSave m_tDefault;
  196. public:
  197.         CTreeSingeLineTree(int iMinIndex, int iMaxIndex, TSave tDefault) {
  198.                 m_tDefault = tDefault;
  199.                 m_root = CreateNode(iMinIndex, iMaxIndex);
  200.         }
  201.         void Init() {
  202.                 Init(m_root);
  203.         }
  204.         void Update(int index, TRecord update) {
  205.                 Update(m_root, index, update);
  206.         }
  207.         TSave QueryAll() {
  208.                 return m_root->data;
  209.         }
  210.         TSave Query(int leftIndex, int leftRight) {
  211.                 TSave ans = m_tDefault;
  212.                 Query(ans, m_root, leftIndex, leftRight);
  213.                 return ans;
  214.         }
  215.         ~CTreeSingeLineTree() {
  216.                 delete m_root;
  217.         }
  218. protected:
  219.         void Query(TSave& ans, CTreeNode* node, int iQueryLeft, int iQueryRight) {
  220.                 if ((node->m_iMinIndex >= iQueryLeft) && (node->m_iMaxIndex <= iQueryRight)) {
  221.                         this->OnQuery(ans, node->data);
  222.                         return;
  223.                 }
  224.                 if (1 == node->Cnt()) {//没有子节点
  225.                         return;
  226.                 }
  227.                 CreateChilds(node);
  228.                 const int mid = node->m_iMinIndex + (node->m_iMaxIndex - node->m_iMinIndex) / 2;
  229.                 if (mid >= iQueryLeft) {
  230.                         Query(ans, node->m_lChild, iQueryLeft, iQueryRight);
  231.                 }
  232.                 if (mid + 1 <= iQueryRight) {
  233.                         Query(ans, node->m_rChild, iQueryLeft, iQueryRight);
  234.                 }
  235.         }
  236.         void Init(CTreeNode* node)
  237.         {
  238.                 if (1 == node->Cnt()) {
  239.                         this->OnInit(node->data, node->m_iMinIndex);
  240.                         return;
  241.                 }
  242.                 CreateChilds(node);
  243.                 Init(node->m_lChild);
  244.                 Init(node->m_rChild);
  245.                 this->OnUpdateParent(node->data, node->m_lChild->data, node->m_rChild->data, node->m_iMinIndex, node->m_iMaxIndex);
  246.         }
  247.         void Update(CTreeNode* node, int iUpdateNO, TRecord update) {
  248.                 if ((iUpdateNO < node->m_iMinIndex) || (iUpdateNO > node->m_iMaxIndex)) {
  249.                         return;
  250.                 }
  251.                 if (1 == node->Cnt()) {
  252.                         this->OnUpdate(node->data, node->m_iMinIndex, update);
  253.                         return;
  254.                 }
  255.                 CreateChilds(node);
  256.                 Update(node->m_lChild, iUpdateNO, update);
  257.                 Update(node->m_rChild, iUpdateNO, update);
  258.                 this->OnUpdateParent(node->data, node->m_lChild->data, node->m_rChild->data, node->m_iMinIndex, node->m_iMaxIndex);
  259.         }
  260.         void CreateChilds(CTreeNode* node) {
  261.                 if (nullptr != node->m_lChild) { return; }
  262.                 const int iSaveLeft = node->m_iMinIndex;
  263.                 const int iSaveRight = node->m_iMaxIndex;
  264.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  265.                 node->m_lChild = CreateNode(iSaveLeft, mid);
  266.                 node->m_rChild = CreateNode(mid + 1, iSaveRight);
  267.         }
  268.         CTreeNode* CreateNode(int iMinIndex, int iMaxIndex) {
  269.                 CTreeNode* node = new CTreeNode;
  270.                 node->m_iMinIndex = iMinIndex;
  271.                 node->m_iMaxIndex = iMaxIndex;
  272.                 node->data = m_tDefault;
  273.                 return node;
  274.         }
  275. };
  276. typedef int TSave;
  277. typedef int  TRecord;
  278. class  CMyLineTree : public  CTreeSingeLineTree<TSave, TRecord>
  279. {
  280. public:
  281.         using CTreeSingeLineTree<TSave, TRecord>::CTreeSingeLineTree;
  282. protected:
  283.         virtual void OnInit(TSave& save, int iSave) {}
  284.         virtual void OnQuery(TSave& ans, const TSave& cur) {
  285.                 ans += cur;
  286.         }
  287.         virtual void OnUpdate(TSave& save, int iSave, const TRecord& update) {
  288.                 save += update;
  289.         }
  290.         virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) {
  291.                 par = left + r;
  292.         }
  293. };
  294. class Solution {
  295. public:
  296.         vector<int> Ans(vector<int>& a, vector<tuple<int, int, int>>& que) {
  297.                 const int N = a.size();
  298.                 int M = *max_element(a.begin(), a.end());
  299.                 vector<int> queCnt(M + 1);
  300.                 for (int i = 0; i < que.size(); i++) {
  301.                         const int c = get<2>(que[i]);
  302.                         if (c > M) { continue; }
  303.                         queCnt[c]++;
  304.                 }
  305.                 vector<CMyLineTree*> lineTrees(M + 1);
  306.                 for (int i = 0; i <= M; i++) {
  307.                         if (0 == queCnt[i])continue;
  308.                         lineTrees[i] = new CMyLineTree(1, N, 0);
  309.                 }
  310.                 for (int i = 1; i <= N; i++) {
  311.                         if (nullptr == lineTrees[a[i - 1]]) { continue; }
  312.                         lineTrees[a[i - 1]]->Update(i, 1);
  313.                 }
  314.                 auto Update = [&](int color, int x, int val) {
  315.                         if (nullptr == lineTrees[color]) { return; }
  316.                         lineTrees[color]->Update(x, val);
  317.                 };
  318.                 vector<int> ans;
  319.                 for (const auto& [left, r, c] : que) {
  320.                         if (0 != r) {
  321.                                 if ((c > M) || (nullptr == lineTrees[c])) {
  322.                                         ans.emplace_back(0);
  323.                                 }
  324.                                 else {
  325.                                         ans.emplace_back(lineTrees[c]->Query(left, r));
  326.                                         queCnt[c]--;
  327.                                         if (0 == queCnt[c]) {
  328.                                                 delete lineTrees[c];
  329.                                                 lineTrees[c] = nullptr;
  330.                                         }
  331.                                 }
  332.                         }
  333.                         else {
  334.                                 Update(a[left - 1], left, -1);
  335.                                 Update(a[left], left + 1, -1);
  336.                                 swap(a[left - 1], a[left]);
  337.                                 Update(a[left - 1], left, 1);
  338.                                 Update(a[left], left + 1, 1);
  339.                         }
  340.                 }
  341.                 return ans;
  342.         }
  343. };
  344. int main() {       
  345. #ifdef _DEBUG
  346.         freopen("a.in", "r", stdin);
  347. #endif // DEBUG               
  348.         int n,q;
  349.         cin >> n >> q;
  350.         auto a = Read<int>(n);
  351.         vector<tuple<int, int, int>> que(q);
  352.                 int kind;
  353.                 for (int i = 0; i < q; i++) {
  354.                         cin >> kind >> get<0>(que[i]) ;
  355.                         if (1 == kind) {
  356.                                 cin >> get<1>(que[i]) >> get<2>(que[i]);
  357.                         }
  358.                 }
  359. #ifdef _DEBUG               
  360.                 /*printf("T=%d,", T);*/
  361.                 /*Out(a, "a=");
  362.                 Out(que, "que=");*/
  363. #endif // DEBUG       
  364.                 auto res = Solution().Ans(a,que);
  365.                 for (const auto& i : res)
  366.                 {
  367.                         cout << i << endl;
  368.                 }
  369.         return 0;
  370. }
复制代码
delete在洛谷用部分用

  1. int main() {       
  2.         vector<int*> v(300);
  3.         for (int i = 0; i < 300; i++) {
  4.                 v[i] = new int[1024 * 1024];
  5.                 if (i >= 10) {
  6.                         delete v[i - 10];
  7.                         v[i - 10] = nullptr;
  8.                 }
  9.         }       
  10.         return 0;
  11. }
复制代码
实验了两次,都是一个样例22M,别的样例1M 以内。

再次优化

20个节点,只用向量。凌驾20个节点用动态线段树。
优化前,有7个凌驾或接近256M,优化后最高占用60M内存,别的最多20M。线段树的节点越多,公共祖先越多。
  1. #include <iostream>
  2. #include <sstream>
  3. #include <vector>
  4. #include<map>
  5. #include<unordered_map>
  6. #include<set>
  7. #include<unordered_set>
  8. #include<string>
  9. #include<algorithm>
  10. #include<functional>
  11. #include<queue>
  12. #include <stack>
  13. #include<iomanip>
  14. #include<numeric>
  15. #include <math.h>
  16. #include <climits>
  17. #include<assert.h>
  18. #include<cstring>
  19. #include<list>
  20. #include <bitset>
  21. using namespace std;
  22. template<class T1, class T2>
  23. std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {
  24.         in >> pr.first >> pr.second;
  25.         return in;
  26. }
  27. template<class T1, class T2, class T3 >
  28. std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {
  29.         in >> get<0>(t) >> get<1>(t) >> get<2>(t);
  30.         return in;
  31. }
  32. template<class T1, class T2, class T3, class T4 >
  33. std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {
  34.         in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);
  35.         return in;
  36. }
  37. template<class T = int>
  38. vector<T> Read() {
  39.         int n;
  40.         scanf("%d", &n);
  41.         vector<T> ret(n);
  42.         for (int i = 0; i < n; i++) {
  43.                 cin >> ret[i];
  44.         }
  45.         return ret;
  46. }
  47. template<class T = int>
  48. vector<T> Read(int n) {
  49.         vector<T> ret(n);
  50.         for (int i = 0; i < n; i++) {
  51.                 cin >> ret[i];
  52.         }
  53.         return ret;
  54. }
  55. template<int N = 1'000'000>
  56. class COutBuff
  57. {
  58. public:
  59.         COutBuff() {
  60.                 m_p = puffer;
  61.         }
  62.         template<class T>
  63.         void write(T x) {
  64.                 int num[28], sp = 0;
  65.                 if (x < 0)
  66.                         *m_p++ = '-', x = -x;
  67.                 if (!x)
  68.                         *m_p++ = 48;
  69.                 while (x)
  70.                         num[++sp] = x % 10, x /= 10;
  71.                 while (sp)
  72.                         *m_p++ = num[sp--] + 48;
  73.                 AuotToFile();
  74.         }
  75.         inline void write(char ch)
  76.         {
  77.                 *m_p++ = ch;
  78.                 AuotToFile();
  79.         }
  80.         inline void ToFile() {
  81.                 fwrite(puffer, 1, m_p - puffer, stdout);
  82.                 m_p = puffer;
  83.         }       
  84.         ~COutBuff() {
  85.                 ToFile();
  86.         }
  87. private:
  88.         inline void AuotToFile() {
  89.                 if (m_p - puffer > N - 100) {
  90.                         ToFile();
  91.                 }
  92.         }
  93.         char  puffer[N], * m_p;
  94. };
  95. template<int N = 12 * 1'000'000>
  96. class CInBuff
  97. {
  98. public:
  99.         inline CInBuff() {
  100.                 fread(buffer, 1, N, stdin);
  101.         }
  102.         inline int Read() {
  103.                 int x(0), f(0);
  104.                 while (!isdigit(*S))
  105.                         f |= (*S++ == '-');
  106.                 while (isdigit(*S))
  107.                         x = (x << 1) + (x << 3) + (*S++ ^ 48);
  108.                 return f ? -x : x;
  109.         }
  110. private:
  111.         char buffer[N], * S = buffer;
  112. };
  113. template<class TSave, class TRecord >
  114. class CSingeUpdateLineTree
  115. {
  116. protected:
  117.         virtual void OnInit(TSave& save, int iSave) = 0;
  118.         virtual void OnQuery(TSave& ans, const TSave& cur) = 0;
  119.         virtual void OnUpdate(TSave& save, int iSave, const TRecord& update) = 0;
  120.         virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) = 0;
  121. };
  122. template<class TSave, class TRecord >
  123. class CVectorSingUpdateLineTree : public CSingeUpdateLineTree<TSave, TRecord>
  124. {
  125. public:
  126.         CVectorSingUpdateLineTree(int iEleSize, TSave tDefault) :m_iEleSize(iEleSize), m_save(iEleSize * 4, tDefault), m_tDefault(tDefault) {
  127.         }
  128.         void Update(int index, TRecord update) {
  129.                 Update(1, 0, m_iEleSize - 1, index, update);
  130.         }
  131.         TSave Query(int leftIndex, int leftRight) {
  132.                 TSave ans;
  133.                 Query(1, 0, m_iEleSize - 1, leftIndex, leftRight);
  134.                 return ans;
  135.         }
  136.         void Init() {
  137.                 Init(1, 0, m_iEleSize - 1);
  138.         }
  139.         TSave QueryAll() {
  140.                 return m_save[1];
  141.         }
  142. protected:
  143.         int m_iEleSize;
  144.         void Init(int iNodeNO, int iSaveLeft, int iSaveRight)
  145.         {
  146.                 if (iSaveLeft == iSaveRight) {
  147.                         this->OnInit(m_save[iNodeNO], iSaveLeft);
  148.                         return;
  149.                 }
  150.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  151.                 Init(iNodeNO * 2, iSaveLeft, mid);
  152.                 Init(iNodeNO * 2 + 1, mid + 1, iSaveRight);
  153.                 this->OnUpdateParent(m_save[iNodeNO], m_save[iNodeNO * 2], m_save[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);
  154.         }
  155.         void Query(TSave& ans, int iNodeNO, int iSaveLeft, int iSaveRight, int iQueryLeft, int iQueryRight) {
  156.                 if ((iSaveLeft >= iQueryLeft) && (iSaveRight <= iQueryRight)) {
  157.                         this->OnQuery(ans, m_save[iNodeNO]);
  158.                         return;
  159.                 }
  160.                 if (iSaveLeft == iSaveRight) {//没有子节点
  161.                         return;
  162.                 }
  163.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  164.                 if (mid >= iQueryLeft) {
  165.                         Query(iNodeNO * 2, iSaveLeft, mid, iQueryLeft, iQueryRight);
  166.                 }
  167.                 if (mid + 1 <= iQueryRight) {
  168.                         Query(iNodeNO * 2 + 1, mid + 1, iSaveRight, iQueryLeft, iQueryRight);
  169.                 }
  170.         }
  171.         void Update(int iNodeNO, int iSaveLeft, int iSaveRight, int iUpdateNO, TRecord update) {
  172.                 if (iSaveLeft == iSaveRight)
  173.                 {
  174.                         this->OnUpdate(m_save[iNodeNO], iSaveLeft, update);
  175.                         return;
  176.                 }
  177.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  178.                 if (iUpdateNO <= mid) {
  179.                         Update(iNodeNO * 2, iSaveLeft, mid, iUpdateNO, update);
  180.                 }
  181.                 else {
  182.                         Update(iNodeNO * 2 + 1, mid + 1, iSaveRight, iUpdateNO, update);
  183.                 }
  184.                 this->OnUpdateParent(m_save[iNodeNO], m_save[iNodeNO * 2], m_save[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);
  185.         }
  186.         vector<TSave> m_save;
  187.         const TSave m_tDefault;
  188. };
  189. template<class TSave, class TRecord >
  190. class CTreeSingeLineTree : public CSingeUpdateLineTree<TSave, TRecord>
  191. {
  192. protected:
  193.         struct CTreeNode
  194.         {
  195.                 int Cnt()const { return m_iMaxIndex - m_iMinIndex + 1; }
  196.                 int m_iMinIndex;
  197.                 int m_iMaxIndex;
  198.                 TSave data;
  199.                 CTreeNode* m_lChild = nullptr, * m_rChild = nullptr;
  200.                 ~CTreeNode() {
  201.                         delete m_lChild; m_lChild = nullptr;
  202.                         delete m_rChild; m_rChild = nullptr;
  203.                 }
  204.         };
  205.         CTreeNode* m_root;
  206.         TSave m_tDefault;
  207. public:
  208.         CTreeSingeLineTree(int iMinIndex, int iMaxIndex, TSave tDefault) {
  209.                 m_tDefault = tDefault;
  210.                 m_root = CreateNode(iMinIndex, iMaxIndex);
  211.         }
  212.         void Init() {
  213.                 Init(m_root);
  214.         }
  215.         void Update(int index, TRecord update) {
  216.                 Update(m_root, index, update);
  217.         }
  218.         TSave QueryAll() {
  219.                 return m_root->data;
  220.         }
  221.         TSave Query(int leftIndex, int leftRight) {
  222.                 TSave ans = m_tDefault;
  223.                 Query(ans, m_root, leftIndex, leftRight);
  224.                 return ans;
  225.         }
  226.         ~CTreeSingeLineTree() {
  227.                 delete m_root;
  228.         }
  229. protected:
  230.         void Query(TSave& ans, CTreeNode* node, int iQueryLeft, int iQueryRight) {
  231.                 if ((node->m_iMinIndex >= iQueryLeft) && (node->m_iMaxIndex <= iQueryRight)) {
  232.                         this->OnQuery(ans, node->data);
  233.                         return;
  234.                 }
  235.                 if (1 == node->Cnt()) {//没有子节点
  236.                         return;
  237.                 }
  238.                 CreateChilds(node);
  239.                 const int mid = node->m_iMinIndex + (node->m_iMaxIndex - node->m_iMinIndex) / 2;
  240.                 if (mid >= iQueryLeft) {
  241.                         Query(ans, node->m_lChild, iQueryLeft, iQueryRight);
  242.                 }
  243.                 if (mid + 1 <= iQueryRight) {
  244.                         Query(ans, node->m_rChild, iQueryLeft, iQueryRight);
  245.                 }
  246.         }
  247.         void Init(CTreeNode* node)
  248.         {
  249.                 if (1 == node->Cnt()) {
  250.                         this->OnInit(node->data, node->m_iMinIndex);
  251.                         return;
  252.                 }
  253.                 CreateChilds(node);
  254.                 Init(node->m_lChild);
  255.                 Init(node->m_rChild);
  256.                 this->OnUpdateParent(node->data, node->m_lChild->data, node->m_rChild->data, node->m_iMinIndex, node->m_iMaxIndex);
  257.         }
  258.         void Update(CTreeNode* node, int iUpdateNO, TRecord update) {
  259.                 if ((iUpdateNO < node->m_iMinIndex) || (iUpdateNO > node->m_iMaxIndex)) {
  260.                         return;
  261.                 }
  262.                 if (1 == node->Cnt()) {
  263.                         this->OnUpdate(node->data, node->m_iMinIndex, update);
  264.                         return;
  265.                 }
  266.                 CreateChilds(node);
  267.                 Update(node->m_lChild, iUpdateNO, update);
  268.                 Update(node->m_rChild, iUpdateNO, update);
  269.                 this->OnUpdateParent(node->data, node->m_lChild->data, node->m_rChild->data, node->m_iMinIndex, node->m_iMaxIndex);
  270.         }
  271.         void CreateChilds(CTreeNode* node) {
  272.                 if (nullptr != node->m_lChild) { return; }
  273.                 const int iSaveLeft = node->m_iMinIndex;
  274.                 const int iSaveRight = node->m_iMaxIndex;
  275.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  276.                 node->m_lChild = CreateNode(iSaveLeft, mid);
  277.                 node->m_rChild = CreateNode(mid + 1, iSaveRight);
  278.         }
  279.         CTreeNode* CreateNode(int iMinIndex, int iMaxIndex) {
  280.                 CTreeNode* node = new CTreeNode;
  281.                 node->m_iMinIndex = iMinIndex;
  282.                 node->m_iMaxIndex = iMaxIndex;
  283.                 node->data = m_tDefault;
  284.                 return node;
  285.         }
  286. };
  287. typedef int TSave;
  288. typedef int  TRecord;
  289. class  CMyLineTree : public  CTreeSingeLineTree<TSave, TRecord>
  290. {
  291. public:
  292.         using CTreeSingeLineTree<TSave, TRecord>::CTreeSingeLineTree;
  293. protected:
  294.         virtual void OnInit(TSave& save, int iSave) {}
  295.         virtual void OnQuery(TSave& ans, const TSave& cur) {
  296.                 ans += cur;
  297.         }
  298.         virtual void OnUpdate(TSave& save, int iSave, const TRecord& update) {
  299.                 save += update;
  300.         }
  301.         virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) {
  302.                 par = left + r;
  303.         }
  304. };
  305. class Solution {
  306. public:
  307.         vector<int> Ans(vector<int>& a, vector<tuple<int, int, int>>& que) {
  308.                 const int N = a.size();
  309.                 int M = *max_element(a.begin(), a.end());
  310.                 vector<int> colorCnt(M + 1);
  311.                 for (const auto& i : a) {
  312.                         colorCnt[i]++;
  313.                 }
  314.                 vector<CMyLineTree*> lineTrees(M + 1);
  315.                 vector<vector<int>> v(M + 1);
  316.                 for (int i = 0; i <= M; i++) {
  317.                         if (colorCnt[i] <= 20) {
  318.                                 continue;
  319.                         }
  320.                         lineTrees[i] = new CMyLineTree(1, N, 0);
  321.                 }
  322.                 for (int i = 1; i <= N; i++) {
  323.                         if (colorCnt[a[i - 1]] <= 20) {
  324.                                 v[a[i - 1]].emplace_back(i);
  325.                                 continue;
  326.                         }
  327.                         lineTrees[a[i - 1]]->Update(i, 1);
  328.                 }
  329.                 auto Update = [&](int color, int x, int val) {
  330.                         if (colorCnt[color] <= 20) {
  331.                                 if (-1 == val) {
  332.                                         for (auto& i : v[color]) {
  333.                                                 if (x == i) {
  334.                                                         i = -1; break;
  335.                                                 }
  336.                                         }
  337.                                 }
  338.                                 else {
  339.                                         for (auto& i : v[color]) {
  340.                                                 if (-1 == i) {
  341.                                                         i = x; break;
  342.                                                 }
  343.                                         }
  344.                                 }
  345.                         }
  346.                         else {
  347.                                 lineTrees[color]->Update(x, val);
  348.                         }
  349.                 };
  350.                 vector<int> ans;
  351.                 for (const auto& [left, r, c] : que) {
  352.                         if (0 != r) {
  353.                                 if (c > M) {
  354.                                         ans.emplace_back(0);
  355.                                 }
  356.                                 else if (colorCnt[c] <= 20) {
  357.                                         auto it1 = lower_bound(v[c].begin(), v[c].end(), left);
  358.                                         auto it2 = upper_bound(v[c].begin(), v[c].end(), r);
  359.                                         ans.emplace_back(it2 - it1);
  360.                                 }
  361.                                 else {
  362.                                         ans.emplace_back(lineTrees[c]->Query(left, r));
  363.                                 }
  364.                         }
  365.                         else {
  366.                                 Update(a[left - 1], left, -1);
  367.                                 Update(a[left], left + 1, -1);
  368.                                 swap(a[left - 1], a[left]);
  369.                                 Update(a[left - 1], left, 1);
  370.                                 Update(a[left], left + 1, 1);
  371.                         }
  372.                 }
  373.                 return ans;
  374.         }
  375. };
  376. int main() {       
  377. #ifdef _DEBUG
  378.         freopen("a.in", "r", stdin);
  379. #endif // DEBUG               
  380.         int n,q;
  381.         cin >> n >> q;
  382.         auto a = Read<int>(n);
  383.         vector<tuple<int, int, int>> que(q);
  384.                 int kind;
  385.                 for (int i = 0; i < q; i++) {
  386.                         cin >> kind >> get<0>(que[i]) ;
  387.                         if (1 == kind) {
  388.                                 cin >> get<1>(que[i]) >> get<2>(que[i]);
  389.                         }
  390.                 }
  391. #ifdef _DEBUG               
  392.                 /*printf("T=%d,", T);*/
  393.                 /*Out(a, "a=");
  394.                 Out(que, "que=");*/
  395. #endif // DEBUG       
  396.                 auto res = Solution().Ans(a,que);       
  397.                 COutBuff bf;
  398.                 for (const auto& i : res )
  399.                 {                       
  400.                         bf.write(i);
  401.                         bf.write('\n');
  402.                 }
  403.         return 0;
  404. }
复制代码
二分查找

用有序集合记录各颜色的下标,然后二分查找。
本题非常巧,可以用向量代替。本题不需要增加、删除向量元素,只需要修改,且修改后依然游戏。
令x的颜色是c,x+1的颜色是c2。
it 指向v[c][x] ,(*it)++
it2指向v[c2][x+1] ,(*it)–。
注意:c1和c2相称,忽略。
代码

  1. #include <iostream>
  2. #include <sstream>
  3. #include <vector>
  4. #include<map>
  5. #include<unordered_map>
  6. #include<set>
  7. #include<unordered_set>
  8. #include<string>
  9. #include<algorithm>
  10. #include<functional>
  11. #include<queue>
  12. #include <stack>
  13. #include<iomanip>
  14. #include<numeric>
  15. #include <math.h>
  16. #include <climits>
  17. #include<assert.h>
  18. #include<cstring>
  19. #include<list>
  20. #include <bitset>
  21. using namespace std;
  22. template<class T1, class T2>
  23. std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {
  24.         in >> pr.first >> pr.second;
  25.         return in;
  26. }
  27. template<class T1, class T2, class T3 >
  28. std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {
  29.         in >> get<0>(t) >> get<1>(t) >> get<2>(t);
  30.         return in;
  31. }
  32. template<class T1, class T2, class T3, class T4 >
  33. std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {
  34.         in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);
  35.         return in;
  36. }
  37. template<class T = int>
  38. vector<T> Read() {
  39.         int n;
  40.         scanf("%d", &n);
  41.         vector<T> ret(n);
  42.         for (int i = 0; i < n; i++) {
  43.                 cin >> ret[i];
  44.         }
  45.         return ret;
  46. }
  47. template<class T = int>
  48. vector<T> Read(int n) {
  49.         vector<T> ret(n);
  50.         for (int i = 0; i < n; i++) {
  51.                 cin >> ret[i];
  52.         }
  53.         return ret;
  54. }
  55. template<int N = 1'000'000>
  56. class COutBuff
  57. {
  58. public:
  59.         COutBuff() {
  60.                 m_p = puffer;
  61.         }
  62.         template<class T>
  63.         void write(T x) {
  64.                 int num[28], sp = 0;
  65.                 if (x < 0)
  66.                         *m_p++ = '-', x = -x;
  67.                 if (!x)
  68.                         *m_p++ = 48;
  69.                 while (x)
  70.                         num[++sp] = x % 10, x /= 10;
  71.                 while (sp)
  72.                         *m_p++ = num[sp--] + 48;
  73.                 AuotToFile();
  74.         }
  75.         inline void write(char ch)
  76.         {
  77.                 *m_p++ = ch;
  78.                 AuotToFile();
  79.         }
  80.         inline void ToFile() {
  81.                 fwrite(puffer, 1, m_p - puffer, stdout);
  82.                 m_p = puffer;
  83.         }       
  84.         ~COutBuff() {
  85.                 ToFile();
  86.         }
  87. private:
  88.         inline void AuotToFile() {
  89.                 if (m_p - puffer > N - 100) {
  90.                         ToFile();
  91.                 }
  92.         }
  93.         char  puffer[N], * m_p;
  94. };
  95. template<int N = 12 * 1'000'000>
  96. class CInBuff
  97. {
  98. public:
  99.         inline CInBuff() {
  100.                 fread(buffer, 1, N, stdin);
  101.         }
  102.         inline int Read() {
  103.                 int x(0), f(0);
  104.                 while (!isdigit(*S))
  105.                         f |= (*S++ == '-');
  106.                 while (isdigit(*S))
  107.                         x = (x << 1) + (x << 3) + (*S++ ^ 48);
  108.                 return f ? -x : x;
  109.         }
  110. private:
  111.         char buffer[N], * S = buffer;
  112. };
  113. template<class TSave, class TRecord >
  114. class CSingeUpdateLineTree
  115. {
  116. protected:
  117.         virtual void OnInit(TSave& save, int iSave) = 0;
  118.         virtual void OnQuery(TSave& ans, const TSave& cur) = 0;
  119.         virtual void OnUpdate(TSave& save, int iSave, const TRecord& update) = 0;
  120.         virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) = 0;
  121. };
  122. template<class TSave, class TRecord >
  123. class CVectorSingUpdateLineTree : public CSingeUpdateLineTree<TSave, TRecord>
  124. {
  125. public:
  126.         CVectorSingUpdateLineTree(int iEleSize, TSave tDefault) :m_iEleSize(iEleSize), m_save(iEleSize * 4, tDefault), m_tDefault(tDefault) {
  127.         }
  128.         void Update(int index, TRecord update) {
  129.                 Update(1, 0, m_iEleSize - 1, index, update);
  130.         }
  131.         TSave Query(int leftIndex, int leftRight) {
  132.                 TSave ans;
  133.                 Query(1, 0, m_iEleSize - 1, leftIndex, leftRight);
  134.                 return ans;
  135.         }
  136.         void Init() {
  137.                 Init(1, 0, m_iEleSize - 1);
  138.         }
  139.         TSave QueryAll() {
  140.                 return m_save[1];
  141.         }
  142. protected:
  143.         int m_iEleSize;
  144.         void Init(int iNodeNO, int iSaveLeft, int iSaveRight)
  145.         {
  146.                 if (iSaveLeft == iSaveRight) {
  147.                         this->OnInit(m_save[iNodeNO], iSaveLeft);
  148.                         return;
  149.                 }
  150.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  151.                 Init(iNodeNO * 2, iSaveLeft, mid);
  152.                 Init(iNodeNO * 2 + 1, mid + 1, iSaveRight);
  153.                 this->OnUpdateParent(m_save[iNodeNO], m_save[iNodeNO * 2], m_save[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);
  154.         }
  155.         void Query(TSave& ans, int iNodeNO, int iSaveLeft, int iSaveRight, int iQueryLeft, int iQueryRight) {
  156.                 if ((iSaveLeft >= iQueryLeft) && (iSaveRight <= iQueryRight)) {
  157.                         this->OnQuery(ans, m_save[iNodeNO]);
  158.                         return;
  159.                 }
  160.                 if (iSaveLeft == iSaveRight) {//没有子节点
  161.                         return;
  162.                 }
  163.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  164.                 if (mid >= iQueryLeft) {
  165.                         Query(iNodeNO * 2, iSaveLeft, mid, iQueryLeft, iQueryRight);
  166.                 }
  167.                 if (mid + 1 <= iQueryRight) {
  168.                         Query(iNodeNO * 2 + 1, mid + 1, iSaveRight, iQueryLeft, iQueryRight);
  169.                 }
  170.         }
  171.         void Update(int iNodeNO, int iSaveLeft, int iSaveRight, int iUpdateNO, TRecord update) {
  172.                 if (iSaveLeft == iSaveRight)
  173.                 {
  174.                         this->OnUpdate(m_save[iNodeNO], iSaveLeft, update);
  175.                         return;
  176.                 }
  177.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  178.                 if (iUpdateNO <= mid) {
  179.                         Update(iNodeNO * 2, iSaveLeft, mid, iUpdateNO, update);
  180.                 }
  181.                 else {
  182.                         Update(iNodeNO * 2 + 1, mid + 1, iSaveRight, iUpdateNO, update);
  183.                 }
  184.                 this->OnUpdateParent(m_save[iNodeNO], m_save[iNodeNO * 2], m_save[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);
  185.         }
  186.         vector<TSave> m_save;
  187.         const TSave m_tDefault;
  188. };
  189. template<class TSave, class TRecord >
  190. class CTreeSingeLineTree : public CSingeUpdateLineTree<TSave, TRecord>
  191. {
  192. protected:
  193.         struct CTreeNode
  194.         {
  195.                 int Cnt()const { return m_iMaxIndex - m_iMinIndex + 1; }
  196.                 int m_iMinIndex;
  197.                 int m_iMaxIndex;
  198.                 TSave data;
  199.                 CTreeNode* m_lChild = nullptr, * m_rChild = nullptr;
  200.                 ~CTreeNode() {
  201.                         delete m_lChild; m_lChild = nullptr;
  202.                         delete m_rChild; m_rChild = nullptr;
  203.                 }
  204.         };
  205.         CTreeNode* m_root;
  206.         TSave m_tDefault;
  207. public:
  208.         CTreeSingeLineTree(int iMinIndex, int iMaxIndex, TSave tDefault) {
  209.                 m_tDefault = tDefault;
  210.                 m_root = CreateNode(iMinIndex, iMaxIndex);
  211.         }
  212.         void Init() {
  213.                 Init(m_root);
  214.         }
  215.         void Update(int index, TRecord update) {
  216.                 Update(m_root, index, update);
  217.         }
  218.         TSave QueryAll() {
  219.                 return m_root->data;
  220.         }
  221.         TSave Query(int leftIndex, int leftRight) {
  222.                 TSave ans = m_tDefault;
  223.                 Query(ans, m_root, leftIndex, leftRight);
  224.                 return ans;
  225.         }
  226.         ~CTreeSingeLineTree() {
  227.                 delete m_root;
  228.         }
  229. protected:
  230.         void Query(TSave& ans, CTreeNode* node, int iQueryLeft, int iQueryRight) {
  231.                 if ((node->m_iMinIndex >= iQueryLeft) && (node->m_iMaxIndex <= iQueryRight)) {
  232.                         this->OnQuery(ans, node->data);
  233.                         return;
  234.                 }
  235.                 if (1 == node->Cnt()) {//没有子节点
  236.                         return;
  237.                 }
  238.                 CreateChilds(node);
  239.                 const int mid = node->m_iMinIndex + (node->m_iMaxIndex - node->m_iMinIndex) / 2;
  240.                 if (mid >= iQueryLeft) {
  241.                         Query(ans, node->m_lChild, iQueryLeft, iQueryRight);
  242.                 }
  243.                 if (mid + 1 <= iQueryRight) {
  244.                         Query(ans, node->m_rChild, iQueryLeft, iQueryRight);
  245.                 }
  246.         }
  247.         void Init(CTreeNode* node)
  248.         {
  249.                 if (1 == node->Cnt()) {
  250.                         this->OnInit(node->data, node->m_iMinIndex);
  251.                         return;
  252.                 }
  253.                 CreateChilds(node);
  254.                 Init(node->m_lChild);
  255.                 Init(node->m_rChild);
  256.                 this->OnUpdateParent(node->data, node->m_lChild->data, node->m_rChild->data, node->m_iMinIndex, node->m_iMaxIndex);
  257.         }
  258.         void Update(CTreeNode* node, int iUpdateNO, TRecord update) {
  259.                 if ((iUpdateNO < node->m_iMinIndex) || (iUpdateNO > node->m_iMaxIndex)) {
  260.                         return;
  261.                 }
  262.                 if (1 == node->Cnt()) {
  263.                         this->OnUpdate(node->data, node->m_iMinIndex, update);
  264.                         return;
  265.                 }
  266.                 CreateChilds(node);
  267.                 Update(node->m_lChild, iUpdateNO, update);
  268.                 Update(node->m_rChild, iUpdateNO, update);
  269.                 this->OnUpdateParent(node->data, node->m_lChild->data, node->m_rChild->data, node->m_iMinIndex, node->m_iMaxIndex);
  270.         }
  271.         void CreateChilds(CTreeNode* node) {
  272.                 if (nullptr != node->m_lChild) { return; }
  273.                 const int iSaveLeft = node->m_iMinIndex;
  274.                 const int iSaveRight = node->m_iMaxIndex;
  275.                 const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
  276.                 node->m_lChild = CreateNode(iSaveLeft, mid);
  277.                 node->m_rChild = CreateNode(mid + 1, iSaveRight);
  278.         }
  279.         CTreeNode* CreateNode(int iMinIndex, int iMaxIndex) {
  280.                 CTreeNode* node = new CTreeNode;
  281.                 node->m_iMinIndex = iMinIndex;
  282.                 node->m_iMaxIndex = iMaxIndex;
  283.                 node->data = m_tDefault;
  284.                 return node;
  285.         }
  286. };
  287. class Solution {
  288. public:
  289.         vector<int> Ans(vector<int>& a, vector<tuple<int, int, int>>& que) {
  290.                 const int N = a.size();
  291.                 int M = *max_element(a.begin(), a.end());
  292.                 vector<vector<int>> v(M + 1);
  293.                 for (int i = 1; i <= N; i++) {
  294.                         v[a[i - 1]].emplace_back(i);
  295.                 }
  296.                 vector<int> ans;
  297.                 for (const auto& [left, r, c] : que) {
  298.                         if (0 != r) {
  299.                                 if (c > M) {
  300.                                         ans.emplace_back(0);
  301.                                 }
  302.                                 else {
  303.                                         auto it1 = lower_bound(v[c].begin(), v[c].end(), left);
  304.                                         auto it2 = upper_bound(v[c].begin(), v[c].end(), r);
  305.                                         ans.emplace_back(it2 - it1);
  306.                                 }
  307.                         }
  308.                         else {
  309.                                 const auto c1 = a[left - 1];
  310.                                 const auto c2 = a[left];
  311.                                 if (c1 == c2) { continue; }
  312.                                 auto it1 = lower_bound(v[c1].begin(), v[c1].end(), left);
  313.                                 auto it2 = lower_bound(v[c2].begin(), v[c2].end(), left + 1);
  314.                                 (*it1)++; (*it2)--;
  315.                                 swap(a[left - 1], a[left]);
  316.                         }
  317.                 }
  318.                 return ans;
  319.         }
  320. };
  321. int main() {       
  322. #ifdef _DEBUG
  323.         freopen("a.in", "r", stdin);
  324. #endif // DEBUG               
  325.         int n,q;
  326.         cin >> n >> q;
  327.         auto a = Read<int>(n);
  328.         vector<tuple<int, int, int>> que(q);
  329.                 int kind;
  330.                 for (int i = 0; i < q; i++) {
  331.                         cin >> kind >> get<0>(que[i]) ;
  332.                         if (1 == kind) {
  333.                                 cin >> get<1>(que[i]) >> get<2>(que[i]);
  334.                         }
  335.                 }
  336. #ifdef _DEBUG               
  337.                 /*printf("T=%d,", T);*/
  338.                 /*Out(a, "a=");
  339.                 Out(que, "que=");*/
  340. #endif // DEBUG       
  341.                 auto res = Solution().Ans(a,que);       
  342.                 COutBuff bf;
  343.                 for (const auto& i : res )
  344.                 {                       
  345.                         bf.write(i);
  346.                         bf.write('\n');
  347.                 }
  348.         return 0;
  349. }
复制代码
扩展阅读

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

先学简朴的课程,请移步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++**实现。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我可以不吃啊

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表