• 牛客-DongDong数颜色 及其相似题


    大佬博客

    ps:在牛客上做到这题不会,学会之后补了两道相关题。顺便记录一下。

    牛客-DongDong数颜色

    sol:dfs序+莫队,先把树上的点标上dfs序,因为子树的dfs序是连续的,所以子树可以表示为id[x]到id[x] + size[x] + 1,然后就是序列上莫队了(引用自官方题解)

    • dfs序 + 莫队
      #include "bits/stdc++.h"
      using namespace std;
      typedef pair<int, int> PII;
      const int MAXN = 1e5 + 10;
      int c1[MAXN], c2[MAXN], c3[MAXN];
      vector<int> edge[MAXN];
      PII node[MAXN]; 
      int pos, size;
      int ans[MAXN];
      struct Query {
          int l, r;
          int index;
      } q[MAXN];
      void dfs(int u, int f) {
          c2[++pos] = c1[u];
          node[u].first = pos;
          for (int i = 0; i < edge[u].size(); i++) {
              int v = edge[u][i];
              if (v == f) continue;
              dfs(v, u);
          }
          node[u].second = pos;
      }
      bool cmp(Query a, Query b) {
          if ((a.l - 1) / size != (b.l - 1) / size)
              return (a.l - 1) / size < (b.l - 1) / size;
          return a.r < b.r;
      }
      int main() {
          int n, m;
          scanf("%d%d", &n, &m);
          size = sqrt(n);
          for (int i = 1; i <= n; i++)
              scanf("%d", &c1[i]);
          for (int i = 1; i < n; i++) {
              int u, v;
              scanf("%d%d", &u, &v);
              edge[u].push_back(v);
              edge[v].push_back(u);
          }
          dfs(1, -1);
          for (int i = 1; i <= m; i++) {
              int x;
              scanf("%d", &x);
              q[i].l = node[x].first;
              q[i].r = node[x].second;
              q[i].index = i;
          }
          sort (q + 1, q + 1 + m, cmp);
          int l = 1, r = 0, k = 0;
          for (int i = 1; i <= m; i++) {
              while (r < q[i].r) if (++c3[c2[++r]] == 1) k++;
              while (l > q[i].l) if (++c3[c2[--l]] == 1) k++;
              while (r > q[i].r) if (--c3[c2[r--]] == 0) k--;
              while (l < q[i].l) if (--c3[c2[l++]] == 0) k--;
              ans[q[i].index] = k;
          }
          for (int i = 1; i <= m; i++) 
              printf("%d
      ", ans[i]);
          return 0;
      }
      View Code

    ps:由于我菜,官方题解上的另外两种解法没补出来,但是去网上看了其他博主的博客发现可以用树状数组代替莫队的功能,效率更高。数组数组为n*log(n),莫队为n*sqrt(n)

    HDU-3333-Turing Tree

    sol:离线处理,优先处理右区间在前的,不断更新每个颜色下标位置,从而在权值树状数组上统计总和;

    • 树状数组
      #include "bits/stdc++.h"
      using namespace std;
      typedef long long LL;
      const int MAXN = 1e5 + 10;
      struct Query {
          int l, r;
          int index;
      } q[MAXN];
      int a[MAXN], pre[MAXN];
      LL c[MAXN], ans[MAXN];
      map<int, int> mp;
      bool cmp(Query a, Query b) {
          return a.r < b.r;
      }
      int lowbit(int i) {
          return i & (-i);
      }
      void add(int i, int k) {
          while (i < MAXN) {
              c[i] += k;
              i += lowbit(i);
          }
      }
      LL sum(int i) {
          LL res = 0;
          while (i > 0) {
              res += c[i];
              i -= lowbit(i);
          }
          return res;
      }
      int main() {
          int t, n, m;
          scanf("%d", &t);
          while (t--) {
              memset(c, 0, sizeof(c));
              mp.clear();
              scanf("%d", &n);
              for (int i = 1; i <= n; i++)
                  scanf("%d", &a[i]);
              scanf("%d", &m);
              for (int i = 1; i <= m; i++) {
                  scanf("%d%d", &q[i].l, &q[i].r);
                  q[i].index = i;
              }
              sort(q + 1, q + 1 + m, cmp);
              int r = 0;
              for (int i = 1; i <= m; i++) {
                  while (r < q[i].r) {
                      ++r;
                      add(r, a[r]);
                      if (mp.count(a[r])) add(mp[a[r]], -a[r]);
                      mp[a[r]] = r;
                  }
                  ans[q[i].index] = sum(q[i].r) - sum(q[i].l - 1);
              }
              for (int i = 1; i <= m; i++)
                  printf("%lld
      ", ans[i]);
          }
          return 0;
      }
      View Code

    ps:按难易程度这题应该排在上一题上面,完全就是上一题的阉割版。上一题用莫队来写了这一题就用来练树状数组的方法了,不过这题用莫队不一定能过,这份数组数组的代码都跑了468ms,莫队可能会比较极限,没有尝试过。

    CF-703D-Mishka and Interesting sum

    sol:把区间所以数异或起来根据相同数字异或为0的原理得到的就是所有出现次数为奇数的数的异或值,那么联系上面两题,只要把区间内不重复出现的数都异或一遍在和区间内所有数异或一下就是我们的结果了。因为异或和加减法具有同样的一些性质也可以用树状数组来解决。

    • 树状数组+位运算
      #include "bits/stdc++.h"
      using namespace std;
      const int MAXN = 1e6 + 10;
      int a[MAXN], b[MAXN], c[MAXN];
      map<int, int> mp;
      int ans[MAXN];
      struct Query {
          int l, r;
          int index;
      } q[MAXN];
      bool cmp(Query a, Query b) {
          return a.r < b.r;
      }
      int lowbit(int i) {
          return i & (-i);
      }
      void add(int i, int k) {
          while (i < MAXN) {
              c[i] ^= k;
              i += lowbit(i);
          }
      }
      int sum(int i) {
          int _xor = 0;
          while (i > 0) {
              _xor ^= c[i];
              i -= lowbit(i);
          }
          return _xor;
      }
      int main() {
          int n, m;
          scanf("%d", &n);
          for (int i = 1; i <= n; i++) {
              scanf("%d", &a[i]);
              b[i] = a[i] ^ b[i - 1];
          }
          scanf("%d", &m);
          for (int i = 1; i <= m; i++) {
              scanf("%d%d", &q[i].l, &q[i].r);
              q[i].index = i;
          }
          sort(q + 1, q + 1 + m, cmp);
          int r = 0;
          for (int i = 1; i <= m; i++) {
              while (r < q[i].r) {
                  r++;
                  add(r, a[r]);
                  if (mp.count(a[r]))
                      add(mp[a[r]], a[r]);
                  mp[a[r]] = r;
              }
              ans[q[i].index] = (sum(q[i].r) ^ sum(q[i].l - 1)) ^ (b[q[i].r] ^ b[q[i].l - 1]);
          }
          for (int i = 1; i <= m; i++)
              printf("%d
      ", ans[i]);
          return 0;
      }
      View Code

    ps:这题我尝试了莫队,超时了,卡在第14组数据,莫队能过1e5的数据,这题n最大值为1e6。莫队比较好写,但还是树状数组比较快。

    dfs序+莫队,先把树上的点标上dfs序,因为子树的dfs序是连续的,所以子树可以表示为id[x]到id[x]+size[x]+1id[x]id[x]+size[x]+1,然后就是序列上莫队了

  • 相关阅读:
    微信公众号开发的时候code失效的问题
    微信公众平台测试号通过网页授权获取用户的信息
    做了一些mysql的习题 感觉用来应付面试是足够了
    springMVC在使用重定向跳转
    jsp获取标签数据
    再来一次atm机 用文本做的
    django mysql数据库配置
    django url控制器
    django初始要做的事情
    flask学习
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/11448830.html
Copyright © 2020-2023  润新知