BZOJ 3809 Gty的二逼妹子序列

Description:

有一个长度为n的序列, 有一些询问l r a b,表示区间[l,r]中数权值在[a,b]中的数的种类数。

Solution:

nsqrt(n)logn的很容易想到,但是会超。

考虑莫队时如何快速计算答案?把权值分块,块内统计答案,每次询问只需sqrt(n)。

故总的时间复杂度为nsqrt(n)+msqrt(n)

Code:

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <string>
 5 #include <algorithm>
 6 #include <cmath>
 7 
 8 using namespace std;
 9 
10 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
11 const int maxn = 1e5+10, maxm = 1e6+10;
12 int n, m, a[maxn];
13 int bel[maxn], l[maxn], r[maxn], s_block;
14 struct Query
15 {
16     int l, r, a, b, id;
17     void read(int i) { scanf("%d %d %d %d", &l, &r, &a, &b), id = i; }
18     bool operator < (const Query &AI) const { return bel[l] == bel[AI.l] ? r < AI.r : l < AI.l; }
19 }q[maxm];
20 int s[1100], c[maxn], ans[maxm];
21 
22 int calc(int x, int y)
23 {
24     int L = bel[x], R = bel[y], ret = 0;
25     if (L == R)
26     {
27         REP(i, x, y) if (c[i]) ret ++;
28     }
29     else
30     {
31         REP(i, L+1, R-1) ret += s[i];
32         REP(i, x, r[L]) if (c[i]) ret ++;
33         REP(i, l[R], y) if (c[i]) ret ++;
34     }
35     return ret;
36 } 
37 
38 void add(int x) { if (++c[x] == 1) s[bel[x]] ++; }
39 
40 void del(int x) { if (--c[x] == 0) s[bel[x]] --; }
41 
42 void solve()
43 {
44     int now_l = 1, now_r = 0;
45     REP(i, 1, m)
46     {
47         for (; now_r < q[i].r; add(a[++now_r]));
48         for (; now_l > q[i].l; add(a[--now_l]));
49         for (; now_r > q[i].r; del(a[now_r--]));
50         for (; now_l < q[i].l; del(a[now_l++]));
51         ans[q[i].id] = calc(q[i].a, q[i].b);
52     }
53 }
54 
55 int main()
56 {
57     scanf("%d %d", &n, &m);
58     REP(i, 1, n) scanf("%d", &a[i]);
59     int block = int(sqrt(n));
60     REP(i, 1, n)
61     {
62         bel[i] = i/block+1, r[bel[i]] = i;
63         if (i == 1 || bel[i] != bel[i-1]) l[bel[i]] = i;
64     }
65     s_block = n/block+1;
66     REP(i, 1, m) q[i].read(i);
67     sort(q+1, q+m+1);
68     solve();
69     REP(i, 1, m) printf("%d\n", ans[i]);
70     return 0;
71 }
View Code

//if为了省行,少了括号,调了很久

 

 

 

 

posted @ 2017-04-10 22:04  Splay  阅读(261)  评论(0编辑  收藏  举报