莫队分块的几道题目

1. https://hihocoder.com/contest/offers24/problem/4

bzoj弹飞绵羊 跟这道题目一模一样。hihocode的题目数据比较水,暴力也可以过。

分块,块内修改+查询。

学习的别人的代码。

 1 #include<bits/stdc++.h>
 2 #define pb push_back
 3 typedef long long ll;
 4 using namespace std;
 5 typedef pair<int, int> pii;
 6 const int maxn = 1e5 + 10;
 7 
 8 int n, m, k;
 9 int a[maxn];
10 int be[maxn], b[maxn], c[maxn];
11 void up(int i) {
12     if(i + a[i] > n || (i + a[i]) / k != i / k) {
13         b[i] = 1;
14         c[i] = i + a[i];
15     } else {
16         b[i] = b[i + a[i] ] + 1;
17         c[i] = c[i + a[i] ];
18     }
19 }
20 int ask(int i) {
21     int r = 0;
22     while(i <= n) {
23         r += b[i];
24         i = c[i];
25     }
26     return r;
27 }
28 
29 void solve() {
30     scanf("%d", &n);
31     for (int i = 1; i <= n; i++) {
32         scanf("%d", &a[i]);
33     }
34     k = sqrt(n + 0.5);
35     for (int i = n; i >= 1; i--) {
36         up(i);
37     }
38     scanf("%d", &m);
39     int x, y, v;
40     while(m--) {
41         scanf("%d%d", &x, &y);
42         //cout << x << " " << y << endl;
43         if(x == 1) {
44             printf("%d
", ask(y));
45         } else {
46             scanf("%d", &v);
47             a[y] = v;
48             for (int i = y; i >= y / k * k; i--) {
49                 up(i);
50             }
51         }
52     }
53 }
54 
55 int main() {
56    // freopen("test.in", "r", stdin);
57     //freopen("test.out", "w", stdout);
58     solve();
59     return 0;
60 }
View Code

2. https://hihocoder.com/problemset/problem/1553?sid=1172120

区间统计,区间计数,主要是没有线段树区间加和的性质,无法维护,利用分块计算计数,然后用计数分布稀疏的特征进行k次幂的计算,比较难。

  1 #include<bits/stdc++.h>
  2 #define pb push_back
  3 typedef long long ll;
  4 using namespace std;
  5 typedef pair<int, int> pii;
  6 const int maxn = 1e5 + 10;
  7 const int mod = 1e9 + 7;
  8 ll ppow(ll x, ll y) {
  9     if(x == 0) return 0;
 10     if(x == 1 || y == 0) return 1;
 11     ll r = 1;
 12     while(y > 0) {
 13         if(y & 1)
 14             r = (r * x) % mod;
 15         y >>= 1;
 16         x = (x * x) % mod;
 17     }
 18     return r;
 19 }
 20 ll tk[maxn][105];
 21 int n, m, s;
 22 int a[maxn];
 23 int be[maxn];
 24 ll res[maxn];
 25 //map<int, int> ma;
 26 //map<int, int> mc;
 27 int ma[maxn], mc[maxn];
 28 struct node {
 29     int x, y, k, id;
 30     bool operator<(const node&t) const{
 31         if(be[x] == be[t.x]) {
 32             return y < t.y;
 33         }
 34         return x < t.x;
 35     }
 36 };
 37 node q[maxn];
 38 ll cur;
 39 set<int> se;
 40 void add(int x) {
 41     mc[ma[x] ]--;
 42     ++ma[x];
 43     mc[ma[x] ]++;
 44     if(ma[x] == s) {
 45         se.insert(x);
 46     }
 47 }
 48 void del(int x) {
 49     mc[ma[x] ]--;
 50     if(ma[x] == s) {
 51         se.erase(x);
 52     }
 53     --ma[x];
 54     mc[ma[x] ]++;
 55 }
 56 ll f(int k) {
 57     ll r = 0;
 58     for (int i = 1; i < s; i++) {
 59         r = (r + mc[i] * tk[i][k] % mod) % mod;
 60     }
 61     for (int x : se) {
 62         r = (r + tk[ma[x] ][k]) % mod;
 63     }
 64     /*
 65     for (int i = 1; i <= s; i++) {
 66         r = (r + mc[i] * ppow(i, k) % mod) % mod;
 67     }
 68     for (auto i = ma.upper_bound(s); i != ma.end(); i++) {
 69         r = (r + ppow())
 70     }*/
 71     return r;
 72 }
 73 void init() {
 74     for (int i = 0; i <= 100000; i++) {
 75         tk[i][0] = 1;
 76         for (int j = 1; j <=100; j++) {
 77             tk[i][j] = (tk[i][j - 1] * i) % mod;
 78         }
 79     }
 80 }
 81 void solve() {
 82     scanf("%d%d", &n, &m);
 83     //ma.clear();
 84     //mc.clear();
 85     memset(ma, 0, sizeof ma);
 86     memset(mc, 0, sizeof mc);
 87     se.clear();
 88     cur = 0;
 89     s = sqrt(n + 0.5);
 90     for (int i = 1; i <= n; i++) {
 91         scanf("%d", &a[i]);
 92         be[i] = i / s;
 93     }
 94     int x, y, v;
 95     for (int i = 1; i <= m; i++) {
 96         scanf("%d%d%d", &x, &y, &v);
 97         q[i] = {x, y, v, i};
 98     }
 99     sort(q + 1, q + m + 1);
100     for (int i = 1, l = 1, r = 0; i <= m; i++) {
101         //cout << "asd" << endl;
102         while(r < q[i].y) {
103             r++;
104             add(a[r]);
105         }
106         while(l > q[i].x) {
107             l--;
108             add(a[l]);
109         }
110         while(r > q[i].y) {
111             del(a[r]);
112             r--;
113         }
114         while(l < q[i].x) {
115             del(a[l]);
116             l++;
117         }
118         //cout << i << endl;
119         res[q[i].id ] = f(q[i].k);
120        // cout << res[q[i].id ] << endl;
121     }
122     for (int i = 1; i <= m; i++)
123         printf("%lld
", res[i]);
124 }
125 
126 int main() {
127     //freopen("test.in", "r", stdin);
128     //freopen("test.out", "w", stdout);
129     init();
130     int _;
131     scanf("%d", &_);
132     while(_--)
133         solve();
134     return 0;
135 }
View Code

上面的2题算是对分块思想的介绍,主要是知道(l,r),可以很快的计算(l,r+1),(l,r-1),(l+1,r),(l-1,r),然后就可以利用分块的性质。

暂时就这么多吧,有时间做这类题目训练一下。

原文地址:https://www.cnblogs.com/y119777/p/7525068.html