其他分享
首页 > 其他分享> > [学习笔记]数列分块入门九题[LOJ6277-6285]

[学习笔记]数列分块入门九题[LOJ6277-6285]

作者:互联网

Thoughts

打完这九题,感觉脱了一层皮,各种或毒瘤或傻逼的错误,很难只交一次便通过。如果不看题解把这九题打完,不仅分块有所进步,调代码细节的能力也会提升。

做完这九题,让我感觉到分块算法本身思维难度不大,主要是代码的细节问题。而要想用分块解决一个问题,最终要的是找到每个块到底存储什么,这些存储的值能否合并,怎样合并


Solution

T1

  #include <bits/stdc++.h>
  
  const int N = 50000;
  
  int n;
  int opt;
  int l;
  int r;
  int c;
  int len;
  int start;
  int end;
  int v[300];
  int a[N + 30];
  int p[N + 30];
  
  inline void build()
  {
      len = sqrt(n);
      for (int i = 1; i <= n; ++i)
          p[i] = (i - 1) / len + 1;
  }
  
  inline void add(int L, int R, int s)
  {
      if (p[L] == p[R])
          for (int i = L; i <= R; ++i)
              a[i] += s;
      else
      {
          for (int i = L; p[i] == p[L]; ++i)
              a[i] += s;
          for (int i = R; p[i] == p[R]; --i)
              a[i] += s;
          for (int i = p[L] + 1; i <= p[R] - 1; ++i)
              v[i] += s;
      }
  }
  
  int main()
  {
      std::cin >> n;
      for (int i = 1; i <= n; ++i)
          std::cin >> a[i];
      build();
      for (int i = 1; i <= n; ++i)
      {
          std::cin >> opt>> l>> r>> c;
          if (opt == 0)
              add(l, r, c);
          else
              printf ("%d\n", v[p[r]] + a[r]);
      }
      return 0;
  }

T2

  #include <vector>
  #include <cmath>
  #include <cstdio>
  #include <algorithm>
  
  const int N = 50030;
  const int Block = 500;
  
  int n, blo, opt, l, r, c, ans;
  int a[N], p[N], v[Block];
  std::vector <int> b[Block];
  
  inline void rebuild(int num)
  {
      b[num].clear();
      for (int i = blo * (num - 1) + 1; i <= std::min(blo * num, n); ++i)
          b[num].push_back(a[i]);
      std::sort(b[num].begin(), b[num].end());
  }
  
  int main()
  {
      scanf ("%d", &n);
      blo = sqrt(n);
      for (int i = 1; i <= n; ++i)
      {
          scanf ("%d", &a[i]);
          p[i] = (i - 1) / blo + 1;
          b[p[i]].push_back(a[i]);
      }
      for (int i = 1; i <= p[n]; ++i)
          std::sort(b[i].begin(), b[i].end());
      for (int t = 1; t <= n; ++t)
      {
          scanf ("%d%d%d%d", &opt, &l, &r, &c);
          if (opt == 0)
          {
              for (int i = l; i <= std::min(blo * p[l], r); ++i)
                  a[i] += c;
              rebuild(p[l]);
              if (p[l] != p[r])
              {hebing
                  for (int i = r; i > (p[r] - 1) * blo; --i)
                      a[i] += c;
                  rebuild(p[r]);
              }
              for (int i = p[l] + 1; i < p[r]; ++i)
                  v[i] += c;
          }
          else
          {
              ans = 0;
              c *= c;
              for (int i = l; i <= std::min(r, blo * p[l]); ++i)
                  ans += (a[i] + v[p[i]] < c);
              for (int i = r; i > (p[r] - 1) * blo && p[l] != p[r]; --i)
                  ans += (a[i] + v[p[i]] < c);
              for (int i = p[l] + 1; i < p[r]; ++i)
                  ans += std::lower_bound(b[i].begin(), b[i].end(), c - v[i]) - b[i].begin();
              printf ("%d\n", ans);
          }
      }
      return 0;
  }

T3

  #include <vector>
  #include <cmath>
  #include <cstdio>
  #include <algorithm>
  
  const int N =100030;
  const int Block = 500;
  
  int n, blo, opt, l, r, c, x, ans;
  int a[N], p[N], v[Block];
  std::vector <int> b[Block];
  
  inline void rebuild(int num)
  {
      b[num].clear();
      for (int i = blo * (num - 1) + 1; i <= std::min(blo * num, n); ++i)
          b[num].push_back(a[i]);
      std::sort(b[num].begin(), b[num].end());
  }
  
  int main()
  {
      scanf ("%d", &n);
      blo = sqrt(n);
      for (int i = 1; i <= n; ++i)
      {
          scanf ("%d", &a[i]);
          p[i] = (i - 1) / blo + 1;
          b[p[i]].push_back(a[i]);
      }
      for (int i = 1; i <= p[n]; ++i)
          std::sort(b[i].begin(), b[i].end());
      for (int t = 1; t <= n; ++t)
      {
          scanf ("%d%d%d%d", &opt, &l, &r, &c);
          if (opt == 0)
          {
              for (int i = l; i <= std::min(blo * p[l], r); ++i)
                  a[i] += c;
              rebuild(p[l]);
              if (p[l] != p[r])
              {
                  for (int i = r; i > (p[r] - 1) * blo; --i)
                      a[i] += c;
                  rebuild(p[r]);
              }
              for (int i = p[l] + 1; i < p[r]; ++i)
                  v[i] += c;
          }
          else
          {
              ans = -1;
              for (int i = l; i <= std::min(r, blo * p[l]); ++i)
                  if (a[i] + v[p[i]] < c)
                      ans = std::max(a[i] + v[p[i]], ans);
              for (int i = r; i > (p[r] - 1) * blo && p[l] != p[r]; --i)
                  if (a[i] + v[p[i]] < c)
                      ans = std::max(a[i] + v[p[i]], ans);
              for (int i = p[l] + 1; i < p[r]; ++i)
                  if (c - v[i] > b[i][0])
                  {
                      x = std::lower_bound(b[i].begin(), b[i].end(), c - v[i]) - b[i].begin();
                      ans = std::max(b[i][x - 1] + v[i], ans);
                  }
              printf ("%d\n", ans);
          }
      }
      return 0;
  }

T4

  #include <vector>
  #include <cmath>
  #include <cstdio>
  #include <algorithm>
  
  const int N =100030;
  const int Block = 500;
  typedef long long LL;
  
  int n, blo, opt, l, r, x;
  int  p[N];
  LL ans, c;
  LL a[N], v[Block], b[Block];
  
  int main()
  {
      scanf ("%d", &n);
      blo = sqrt(n);
      for (int i = 1; i <= n; ++i)
      {
          scanf ("%lld", &a[i]);
          p[i] = (i - 1) / blo + 1;
          b[p[i]] += a[i];
      }
      for (int t = 1; t <= n; ++t)
      {
          scanf ("%d%d%d%lld", &opt, &l, &r, &c);
          if (opt == 0)
          {
              for (int i = l; i <= std::min(blo * p[l], r); ++i)
              {
                  a[i] += c;
                  b[p[i]] += c;
              }
              for (int i = r; i > (p[r] - 1) * blo && p[l] != p[r]; --i)
              {
                  a[i] += c;
                  b[p[i]] += c;
              }
              for (int i = p[l] + 1; i < p[r]; ++i)
                  v[i] += c;
          }
          else
          {
              ans = 0;
              for (int i = l; i <= std::min(r, blo * p[l]); ++i)
                  ans = (ans + a[i] + v[p[i]]) % (c + 1);
              for (int i = r; i > (p[r] - 1) * blo && p[l] != p[r]; --i)
                  ans = (ans + a[i] + v[p[i]]) % (c + 1);
              for (int i = p[l] + 1; i < p[r]; ++i)
                  ans = (ans + b[i] + v[i] * blo) % (c + 1);
              printf ("%lld\n", ans);
          }
      }
      return 0;
  }

T5

  #include <vector>
  #include <cmath>
  #include <cstdio>
  #include <algorithm>
  
  const int N =100030;
  const int Block = 500;
  typedef long long LL;
  
  int n, blo, opt, l, r, c, x;
  int p[N], a[N], cnt[Block];
  LL ans;
  
  int main()
  {
      scanf ("%d", &n);
      blo = sqrt(n);
      for (int i = 1; i <= n; ++i)
      {
          scanf ("%d", &a[i]);
          p[i] = (i - 1) / blo + 1;
          cnt[p[i]] += (a[i] == 1);
      }
      for (int t = 1; t <= n; ++t)
      {
          scanf ("%d%d%d%d", &opt, &l, &r, &c);
          if (opt == 0)
          {
              for (int i =hebing l; i <= std::min(blo * p[l], r); ++i)
              {
                  if (a[i] > 1)
                  {
                      a[i] = sqrt(a[i]);
                      cnt[p[i]] += (a[i] == 1);
                  }
              }
              for (int i = r; i > (p[r] - 1) * blo && p[l] != p[r]; --i)
              {
                  if (a[i] > 1)
                  {
                      a[i] = sqrt(a[i]);
                      cnt[p[i]] += (a[i] == 1);
                  }
              }
              for (int i = p[l] + 1; i < p[r]; ++i)
                  for (int j = (i - 1) * blo + 1; j <= std::min(n, i * blo) && cnt[i] != blo; ++j)
                      if (a[j] > 1)
                      {
                          a[j] = sqrt(a[j]);
                          cnt[p[j]] += (a[j] == 1);
                      }
          }
          else
          {
              ans = 0;
              for (int i = l; i <= std::min(r, blo * p[l]); ++i)
                  ans += a[i];
              for (int i = r; i > (p[r] - 1) * blo && p[l] != p[r]; --i)
                  ans += a[i];
              for (int i = p[l] + 1; i < p[r]; ++i)
                  if (cnt[i] == blo)
                      ans += blo;
                  else
                      for (int j = (i - 1) * blo + 1; j <= std::min(n, i * blo); ++j)
                          ans += a[j];
              printf ("%lld\n", ans);
          }
      }
      return 0;
  }

T6

  #include <bits/stdc++.h>
  const int N =100030;
  int n, blo, opt, l, r, c, x, m, num, sum, top, a[N], st[N * 2];
  std::vector < int > b[N];
  inline void rebuild() {
      sum = top = 0;
      for (int i = 1; i <= m; ++i) {
          for (std::vector < int >::iterator it = b[i].begin(); it != b[i].end(); ++it) st[++top] = *it;
          b[i].clear();
      }int block2 = sqrt(top);
      for (int i = 1; i <= top; ++i) b[(i - 1) / block2 + 1].push_back(st[i]);
      m = (top - 1) / block2 + 1;
  }int main() {
      scanf ("%d", &n);
      blo = sqrt(n);
      for (int i = 1; i <= n; ++i){
          scanf ("%d", &a[i]);
          b[(i - 1) / blo + 1].push_back(a[i]);
      }m = (n - 1) / blo + 1;
      for (int t = 1; t <= n; ++t) {
          scanf ("%d%d%d%d", &opt, &l, &r, &c);
          if (opt == 0){
              num = 1;
              while (l > b[num].size()) l -= b[num++].size();
              b[num].insert(b[num].begin() + l - 1, r);
              if (++sum == blo) rebuild();
          }else {
              x = 1;
              while (r > b[x].size()) r -= b[x++].size();
              printf ("%d\n", b[x][r - 1]);
          }
      }return 0;
  }

T7

#include <bits/stdc++.h>
const int N = 1000000, Blo = 5000, MOD = 10007;
int n, l, r, c, opt, blo, p[N], fir[Blo], end[Blo];
long long add[Blo], mul[Blo], a[N];
int main() {
    scanf ("%d", &n); blo = sqrt(n);
    for (int i = 1; i <= n; ++i) {
        scanf ("%lld", &a[i]);
        p[i] = (i - 1) / blo + 1;
        if (fir[p[i]] == 0) fir[p[i]] = i;
        end[p[i]] = i; mul[p[i]] = 1; 
    } for (int i = 1; i <= n; ++i) {
        scanf ("%d%d%d%d", &opt, &l, &r, &c);
        if (opt <= 1) {
            for (int i = fir[p[l]]; i <= end[p[l]]; ++i) {
                if (i < l || i > std::min(r,end[p[l]])) a[i] = (a[i] * mul[p[i]] + add[p[i]]) % MOD;
                else if (opt == 0) a[i] = (a[i] * mul[p[i]] + add[p[i]] + c) % MOD;
                else a[i] = (a[i] * mul[p[i]] * c + add[p[i]] * c) % MOD;
                if (i == end[p[l]]) {mul[p[i]] = 1; add[p[i]] = 0;}
            }for (int i = end[p[r]]; i >= fir[p[r]] && p[l] != p[r]; --i) {
                if (i > r) a[i] = (a[i] * mul[p[i]] + add[p[i]]) % MOD;
                else if (opt == 0) a[i] = (a[i] * mul[p[i]] + add[p[i]] + c) % MOD;
                else a[i] = (a[i] * mul[p[i]] * c + add[p[i]] * c) % MOD; 
                if (i == fir[p[r]]) {mul[p[i]] = 1; add[p[i]] = 0;}
            }for (int i = p[l] + 1; i < p[r]; ++i)
                if (opt == 0) add[i] = (add[i] + c) % MOD;
                else {mul[i] = (mul[i] * c) % MOD; add[i] = (add[i] * c) % MOD; }
        }else printf ("%lld\n", (a[r] * mul[p[r]] + add[p[r]]) % MOD);
    }return 0;
}

T8

  #include <cstdio>
  #include <algorithm>
  #include <cmath>
  
  typedef long long LL;
  
  const int N =  1e5 + 30, Blo = 5000;
  const LL INF = 1e12 + 30;
  
  int n, l, r, c, blo, ans;
  int p[N];
  LL a[N], now[Blo];
  
  int main()
  {
      scanf ("%d", &n);
      blo = sqrt(n);
      for (int i = 1; i <= n; ++i)
      {
          scanf ("%lld", &a[i]);
          p[i] = (i - 1) / blo + 1;
          now[p[i]] = INF;
      }
      
      for (int t = 1; t <= n; ++t)
      {
          ans = 0;
          scanf ("%d%d%d", &l, &r, &c);
          for (int i = (p[l] - 1) * blo + 1; i <= std::min(n, p[l] * blo); ++i)
          {
              if ((i < l || i > r) && now[p[i]] != INF) 
                  a[i] = now[p[i]];
              else if (i >= l && i <= r)
              {
                  ans += ((a[i] == c && now[p[i]] == INF) || now[p[i]] == c);
                  a[i] = c;
              }
          }
          
          for (int i = (p[r] - 1) * blo + 1; i <= std::min(n, p[r] * blo) && p[l] != p[r]; ++i)
          {
              if (i > r && now[p[i]] != INF)
                  a[i] = now[p[i]];
              else if (i <= r && i >= l)
              {
                  ans += ((a[i] == c && now[p[i]] == INF) || now[p[i]] == c);
                  a[i] = c;
              }
          }
          now[p[l]] =  now[p[r]] = INF;
  
          for (int i = p[l] + 1; i < p[r]; ++i)
          {
              if (now[i] == c) ans += blo;
              else if (now[i] == INF)
              {
                  for (int j = (i - 1) * blo + 1; j <= i * blo; ++j)
                      ans += (a[j] == c);
              }
              now[i] = c;
          }
          printf ("%d\n", ans);
      }
  
      return 0;
  }

T9

  #include <cstdio>
  #include <cmath>
  #include <algorithm>
  #include <map>
  #include <cstring>
  #include <vector>
  
  const int N = 100030;
  const int BLOCK = 2030;
  
  bool vis[N];
  int n, blo, id, mx, f, l, r, x;
  int a[N], Ans[N], m[BLOCK][BLOCK], p[N], num[N];
  std::map <int, int > mp;
  std::vector < int > v[N];
  
  int get(int left, int right, int now)
  {
      return std::upper_bound(v[now].begin(), v[now].end(), right) - std::lower_bound(v[now].begin(), v[now].end(), left); 
  }
  
  int main()
  {
      scanf ("%d", &n);
      blo = 80;
      for (int i = 1; i <= n; ++i)
      {
          scanf ("%d", &a[i]);
          if (mp[a[i]] == 0)
          {
              mp[a[i]] = ++id;
              Ans[id] = a[i];
          }
          p[i] = (i - 1) / blo + 1;
          a[i] = mp[a[i]];
          v[a[i]].push_back(i);
      }
      for (int i = 1; i <= p[n]; ++i)
      {
          std::memset(num, 0 ,sizeof(num));
          mx = f = 0; 
          for (int j = (i - 1) * blo + 1; j <= n; ++j)
          {
              num[a[j]]++;
              if (num[a[j]] > f || (num[a[j]] == f && Ans[a[j]] < Ans[mx]))
              {
                  mx = a[j];Markdown Theme Kit
      }
      for (int t = 1; t <= n; ++t)
      {
          scanf ("%d%d", &l, &r);
          mx = get(l, r, m[p[l] + 1][p[r] - 1]);
          f = m[p[l] + 1][p[r] - 1];
          std::memset(vis, 0, sizeof(vis));
          vis[f] = 1;
          for (int i = l; i <= std::min(r, p[l] * blo); ++i)
          {
              if (vis[a[i]] == 0)
              {
                  vis[a[i]] = 1;
                  x = get(l, r, a[i]);
                  if (mx < x || mx == x && Ans[a[i]] < Ans[f])
                  {
                      f = a[i];
                      mx = x;
                  }
              }
          }
          for (int i = (p[r] - 1) * blo + 1; i <= r && p[l] != p[r]; ++i)
          {
              if (vis[a[i]] == 0)
              {
                  vis[a[i]] = 1;
                  x = get(l, r, a[i]);
                  if (mx < x || mx == x && Ans[a[i]] < Ans[f])
                  {
                      f = a[i];
                      mx = x;
                  }
              }
          }
          printf ("%d\n", Ans[f]);
      }
      return 0;
  }

Ending

码字不易,欢迎点赞和评论qvq

标签:now,LOJ6277,int,6285,九题,else,blo,ans,include
来源: https://www.cnblogs.com/martixx/p/13550666.html