#12:开学焦虑——4

BZOJ1012,特点是只往后加所以可用单调栈。亦可无脑线段树。

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 int m;
 6 ll D, last;
 7 ll q[200005];
 8 int id[200005], tail, t;
 9 
10 inline void add(ll x) {
11     while (tail && q[tail] <= x)
12         tail--;
13     q[++tail] = x;
14     id[tail] = ++t;
15 }
16 
17 inline ll query(ll x) {
18     ll k = t - x + 1;
19     int pos = lower_bound(id+1, id+1+tail, k) - id;
20     return q[pos];
21 }
22 
23 int main() {
24     cin >> m >> D;
25     while (m--) {
26         char ch[3];
27         ll a;
28         scanf("%s%lld", ch, &a);
29         if (ch[0] == 'A') {
30             add((a + last) % D);
31         } else {
32             printf("%lld
", last = query(a));
33         }
34     }
35     return 0;
36 }
单调栈+二分
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxm = 200005;
 5 int M, D, last, n;
 6 struct Seg {
 7     int l, r, maxx;
 8 }t[maxm << 2];
 9 
10 void build(int l, int r, int p) {
11     t[p].l = l, t[p].r = r;
12     if (l == r) {
13         t[p].maxx = 0;
14         return;
15     }
16     int mid = (l + r) >> 1;
17     int ls = p << 1, rs = p << 1 | 1;
18     build(l, mid, ls);
19     build(mid+1, r, rs);
20     t[p].maxx = max(t[ls].maxx, t[rs].maxx);
21 }
22 
23 void Add(int l, int k, int p) {
24     if (t[p].l == t[p].r) {
25         t[p].maxx = k;
26         return;
27     }
28     int mid = (t[p].l + t[p].r) >> 1;
29     int ls = p << 1, rs = p << 1 | 1;
30     if (l <= mid)    Add(l, k, ls);
31     else    Add(l, k, rs);
32     t[p].maxx = max(t[ls].maxx, t[rs].maxx);
33 }
34 
35 int Query(int l, int r, int p) {
36     if (l <= t[p].l && t[p].r <= r) {
37         return t[p].maxx;
38     }
39     int mid = (t[p].l + t[p].r) >> 1;
40     int ls = p << 1, rs = p << 1 | 1;
41     int ret = 0;
42     if (l <= mid)    ret = max(ret, Query(l, r, ls));
43     if (mid < r)    ret = max(ret, Query(l, r, rs));
44     return ret;
45 }
46 
47 int main() {
48     scanf("%d%d", &M, &D);
49     build(1, M, 1);
50     while (M--) {
51         char ch[3];
52         int x;
53         scanf("%s%d", ch, &x);
54         if (ch[0] == 'A') {
55             ++n;
56             Add(n, (x+last)%D, 1);
57         } else {
58             printf("%d
", last = Query(n-x+1, n, 1));
59         }
60     }
61 }
线段树

BZOJ2724,分块框架下的数据预处理技巧。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <cctype>
 5 #include <iostream>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 #define ri readint()
10 #define gc getchar()
11 #define rep(i, l, r) for (int i = l; i <= r; i++)
12 using namespace std;
13 
14 inline int readint() {
15     int x = 0, s = 1, c = gc;
16     while (c <= 32)    c = gc;
17     if (c == '-')    s = -1, c = gc;
18     for (; isdigit(c); c = gc)
19         x = x * 10 + c - 48;
20     return x * s;
21 }
22 
23 const int maxn = 4e4 + 5;
24 int n, m, T, last;
25 int a[maxn], val[maxn], id;
26 map<int, int> mp;
27 vector<int> v[maxn];
28 int block[maxn], f[205][205];
29 
30 void pre(int x) {
31     int cnt[maxn];
32     memset(cnt, 0, sizeof(cnt));
33     int maxx = 0, k = 0;
34     rep(i, (x - 1) * T + 1, n) {
35         int t = a[i];
36         cnt[t]++;
37         if (cnt[t] > maxx || (cnt[t] == maxx && val[t] < val[k])) {
38             maxx = cnt[k = t];
39         }
40         f[x][block[i]] = k;
41     }
42 }
43 
44 int Query(int ql, int qr, int k) {
45     return upper_bound(v[k].begin(), v[k].end(), qr) - lower_bound(v[k].begin(), v[k].end(), ql);
46 }
47 
48 int Query(int ql, int qr) {
49     int res = f[block[ql]+1][block[qr]-1];
50     int maxx = Query(ql, qr, res);
51     rep(i, ql, min(block[ql]*T, qr)) {
52         int t = Query(ql, qr, a[i]);
53         if (t > maxx || (t == maxx && val[a[i]] < val[res])) {
54             maxx = t;
55             res = a[i];
56         }
57     }
58     if (block[ql] != block[qr]) {
59         rep(i, (block[qr]-1) * T + 1, qr) {
60             int t = Query(ql, qr, a[i]);
61             if (t > maxx || (t == maxx && val[a[i]] < val[res])) {
62                 maxx = t;
63                 res = a[i];
64             }
65         }
66     }
67     return val[res];
68 }
69 
70 int main() {
71     n = ri, m = ri;
72     T = 300;
73 
74     rep(i, 1, n){
75         a[i] = ri;
76         if (!mp[a[i]]) {
77             val[++id] = a[i];
78             mp[a[i]] = id;
79         }
80         v[mp[a[i]]].push_back(i);
81         a[i] = mp[a[i]];
82     }
83     rep(i, 1, n)    block[i] = (i-1) / T + 1;
84     rep(i, 1, block[n])    pre(i);
85 
86     while (m--) {
87         int ql = ri, qr = ri;
88         ql = (ql + last - 1) % n + 1;
89         qr = (qr + last - 1) % n + 1;
90         if (ql > qr)    swap(ql, qr);
91         printf("%d
", last = Query(ql, qr));
92     }
93     return 0;
94 }
View Code

CH#46A,分块下的排序处理便于降低之后bfs的复杂度。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <cctype>
  5 #include <iostream>
  6 #include <algorithm>
  7 #define ll long long
  8 #define ri readint()
  9 #define gc getchar()
 10 #define rep(i, l, r) for (int i = l; i <= r; i++)
 11 using namespace std;
 12 
 13 const int N = 25 * 1e4 + 5;
 14 struct Stone {
 15     ll x, y, m, p, r, d;
 16 }q[N], st[N];
 17 int L[N], R[N], M[N];
 18 int n, T, block;
 19 bool mark[N];
 20 
 21 inline int readint() {
 22     int x = 0, s = 1, c = gc;
 23     while (c <= 32)    c = gc;
 24     if (c == '-')    s = -1, c = gc;
 25     for (; isdigit(c); c = gc)
 26         x = x * 10 + c - 48;
 27     return x * s;
 28 }
 29 
 30 inline ll sqr(ll x) {
 31     return x * x;
 32 }
 33 
 34 inline bool cmp1(const Stone &a, const Stone &b) {
 35     return a.m < b.m;
 36 }
 37 
 38 inline bool cmp2(const Stone &a, const Stone &b) {
 39     return a.d < b.d;
 40 }
 41 
 42 void READ() {
 43     q[0].x = ri, q[0].y = ri, q[0].p = ri, q[0].r = ri;
 44     n = ri;
 45     T = sqrt(n);
 46     rep(i, 1, n) {
 47         st[i].x = ri;
 48         st[i].y = ri;
 49         st[i].m = ri;
 50         st[i].p = ri;
 51         st[i].r = ri;
 52         st[i].d = sqr(st[i].x - q[0].x) + sqr(st[i].y - q[0].y);
 53     }
 54 }
 55 
 56 void BLOCK() {
 57     sort(st+1, st+1+n, cmp1);
 58     block = (n - 1) / T + 1;
 59     rep(i, 1, block) {
 60         L[i] = (i - 1) * T + 1;
 61         R[i] = min(i * T, n);
 62         M[i] = st[R[i]].m;
 63         sort(st+L[i], st+R[i]+1, cmp2);
 64     }
 65 }
 66 
 67 int BFS() {
 68     int l = 0, r = 1;
 69     while (l < r) {
 70         int k = 0;
 71         rep(i, 1, block) {
 72             if (M[i] > q[l].p)
 73                 break;
 74             k = i;
 75         }
 76 
 77         rep(i, 1, k) {
 78             while (L[i] <= R[i] && st[L[i]].d <= sqr(q[l].r)) {
 79                 if (!mark[L[i]]) {
 80                     mark[L[i]] = true;
 81                     q[r++] = st[L[i]];
 82                 }
 83                 ++L[i];
 84             }
 85         }
 86         if (block != k++) {
 87             rep(i, L[k], R[k]) {
 88                 if (!mark[i] && st[i].m <= q[l].p && st[i].d <= sqr(q[l].r)) {
 89                     mark[i] = true;
 90                     q[r++] = st[i];
 91                 }
 92             }
 93         }
 94 
 95         ++l;
 96     }
 97     return r - 1;
 98 }
 99 
100 int main() {
101     READ();
102     BLOCK();
103     cout << BFS() << endl;
104     return 0;
105 }
View Code

BZOJ2038,喜闻乐见的莫队袜子,感觉求概率这个数学式子的变换也是很重要的一环呀。然后分块排序保证了询问均摊根号N的复杂度吧。

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 const int N = 1e5 + 5;
 6 int n, m, col[N];
 7 int T, block[N];
 8 ll ans, sum[N];
 9 struct Mo {
10     int l, r, id;
11     ll A, B;
12 }q[N];
13 
14 bool cmp1(Mo a, Mo b) {
15     return block[a.l] == block[b.l] ? a.r < b.r : a.l < b.l;
16 }
17 
18 bool cmp2(Mo a, Mo b) {
19     return a.id < b.id;
20 }
21 
22 ll sqr(ll x) {
23     return x * x;
24 }
25 
26 void change(int x, int add) {
27     ans -= sqr(sum[col[x]]);
28     sum[col[x]] += add;
29     ans += sqr(sum[col[x]]);
30 }
31 
32 int main() {
33     cin >> n >> m;
34     T = sqrt(n);
35     for (int i = 1; i <= n; i++) {
36         scanf("%d", &col[i]);
37         block[i] = (i - 1) / T + 1;
38     }
39     for (int i = 1; i <= m; i++) {
40         scanf("%d%d", &q[i].l, &q[i].r);
41         q[i].id = i;
42     }
43     sort(q+1, q+1+m, cmp1);
44 
45     int l = 1, r = 0;
46     for (int i = 1; i <= m; i++) {
47         while (l < q[i].l)    change(l++, -1);
48         while (l > q[i].l)    change(--l, 1);
49         while (r < q[i].r)    change(++r, 1);
50         while (r > q[i].r)    change(r--, -1);
51 
52         if (q[i].l == q[i].r) {
53             q[i].A = 0ll;
54             q[i].B = 1ll;
55             continue;
56         }
57         ll t = q[i].r - q[i].l + 1;
58         q[i].A = ans - t;
59         q[i].B = sqr(t) - t;
60         ll gcd = __gcd(q[i].A, q[i].B);
61         if (!gcd)    q[i].B = 1ll;
62         else    q[i].A /= gcd, q[i].B /= gcd;
63     }
64 
65     sort(q+1, q+1+m, cmp2);
66     for (int i = 1; i <= m; i++)
67         printf("%lld/%lld
", q[i].A, q[i].B);
68 
69     return 0;
70 }
View Code
原文地址:https://www.cnblogs.com/AlphaWA/p/10367617.html