洛谷 P4396 [AHOI2013]作业

思路:莫队+分块

这题其实跟Gty的二逼妹子序列
非常像

把那题代码改改就行了

首先区间问题,可以离线,马上想到莫队

然后发现不会修改?怎么办?

(好像可以树状数组做,可是我不会o((⊙﹏⊙))o

我们可以把值域分块,这样就可以做到每次查询$O(\sqrt n)​$,修改$O(1)​$了

总复杂度$O(m \sqrt n)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <bits/stdc++.h>
#define getpos(x) ((x - 1) / block + 1)
#define getblock(x) ((x - 1) * block + 1)
const int MaxN = 100010;
struct query
{
int id, pos;
int l, r, a, b;
};
query q[MaxN];
int n, m, size, block;
int a[MaxN], cnt[MaxN], sum[MaxN][3], ans[MaxN][3];
inline int cmp(query a, query b)
{
if (a.pos != b.pos)
return a.pos < b.pos;
return a.r < b.r;
}
inline int read()
{
int x = 0;
char ch = getchar();
while (ch > '9' || ch < '0')
ch = getchar();
while (ch <= '9' && ch >= '0')
x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return x;
}
inline void add(int x)
{
++cnt[a[x]];
++sum[getpos(a[x])][1];
if (cnt[a[x]] == 1)
++sum[getpos(a[x])][2];
}
inline void del(int x)
{
--cnt[a[x]];
--sum[getpos(a[x])][1];
if (cnt[a[x]] == 0)
--sum[getpos(a[x])][2];
}
inline void ask(int x)
{
int id = q[x].id, l = q[x].a, r = q[x].b, Posl = getpos(q[x].a), Posr = getpos(q[x].b);
for (int i = Posl + 1; i < Posr; i++)
ans[id][1] += sum[i][1], ans[id][2] += sum[i][2];
if (Posl == Posr)
{
for (int i = l; i <= r; i++)
{
ans[id][1] += cnt[i];
if (cnt[i])
ans[id][2]++;
}
}
else
{
int L = getblock(Posr), R = getblock(Posl + 1) - 1;
for (int i = l; i <= R; i++)
{
ans[id][1] += cnt[i];
if (cnt[i])
ans[id][2]++;
}
for (int i = L; i <= r; i++)
{
ans[id][1] += cnt[i];
if (cnt[i])
ans[id][2]++;
}
}
}
inline void solve()
{
int l = 1, r = 0;
for (int i = 1; i <= m; i++)
{
while (l > q[i].l)
--l, add(l);
while (r < q[i].r)
++r, add(r);
while (l < q[i].l)
del(l), l++;
while (r > q[i].r)
del(r), r--;
ask(i);
}
}
int main()
{
n = read(), m = read();
size = pow(n, 0.55), block = sqrt(n);
for (int i = 1; i <= n; ++i)
a[i] = read();
for (int i = 1; i <= m; i++)
{
q[i].l = read(), q[i].r = read();
q[i].a = read(), q[i].b = read();
q[i].id = i, q[i].pos = (q[i].l - 1) / size + 1;
}
std::sort(q + 1, q + m + 1, cmp);
solve();
for (int i = 1; i <= m; i++)
printf("%d %d\n", ans[i][1], ans[i][2]);
return 0;
}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×