洛谷传送门
BZOJ传送门
题目描述
Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题。
对于一段妹子们,他们想让你帮忙求出这之内美丽度 ∈ [ a , b ] \in [a,b] ∈[a,b]的妹子的美丽度的种类数。
为了方便,我们规定妹子们的美丽度全都在
[
1
,
n
]
[1,n]
[1,n]中。
给定一个长度为
n
(
1
≤
n
≤
100000
)
n(1 \le n \le 100000)
n(1≤n≤100000)的正整数序列
s
(
1
≤
s
i
≤
n
)
,
对
s(1 \le s_i \le n),对
s(1≤si≤n),对于
m
(
1
≤
m
≤
1000000
)
m(1 \le m \le 1000000)
m(1≤m≤1000000)次询问l,r,a,b
,每次输出
s
l
⋯
s
r
s_l \cdots s_r
sl⋯sr中,权值
∈
[
a
,
b
]
\in [a,b]
∈[a,b]的权值的种类数。
输入输出格式
输入格式:
第一行包括两个整数 n , m ( 1 ≤ n ≤ 100000 , 1 ≤ m ≤ 1000000 ) n,m(1 \le n \le 100000,1 \le m \le 1000000) n,m(1≤n≤100000,1≤m≤1000000),表示数列 s s s中的元素数和询问数。
第二行包括 n n n个整数 s 1 … s n ( 1 ≤ s i ≤ n ) s_1…s_n(1 \le s_i \le n) s1…sn(1≤si≤n)。
接下来 m m m行,每行包括 4 4 4个整数 l , r , a , b ( 1 ≤ l ≤ r ≤ n , 1 ≤ a ≤ b ≤ n ) l,r,a,b(1 \le l \le r \le n,1 \le a \le b \le n) l,r,a,b(1≤l≤r≤n,1≤a≤b≤n),意义见题目描述。
保证涉及的所有数在C++的int内。保证输入合法。
输出格式:
对每个询问,单独输出一行,表示 s l ⋯ s r s_l \cdots s_r sl⋯sr中权值 ∈ [ a , b ] \in [a,b] ∈[a,b]的权值的种类数。
输入输出样例
输入样例#1:
10 10
4 4 5 1 4 1 5 1 2 1
5 9 1 2
3 4 7 9
4 4 2 5
2 3 4 7
5 10 4 4
3 9 1 1
1 4 5 9
8 9 3 3
2 2 1 6
8 9 1 4
输出样例#1:
2
0
0
2
1
1
1
0
1
2
解题分析
神奇的操作。
显然用线段树配合莫队搞搞, 因为会加入/删除 m n m\sqrt n mn次, 那么总复杂度是 O ( m n l o g ( n ) + m l o g ( n ) ) O(m\sqrt nlog(n)+mlog(n)) O(mnlog(n)+mlog(n))的, 显然不是很能过。
考虑如何均摊这个复杂度。 前面那一坨太大了, 如果能把 l o g ( n ) log(n) log(n)改成 O ( 1 ) O(1) O(1)就好了。
那么显然我们可以对值域分块, 做到 O ( 1 ) O(1) O(1)插入块中, 然后 O ( n ) O(\sqrt n) O(n)遍历小块, O ( n ) O(\sqrt n) O(n)遍历大块做到。
这样总复杂度是 O ( m n + m n ) O(m\sqrt n+m\sqrt n) O(mn+mn), 可以 A A A了。
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <climits>
#include <cstdlib>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 1005000
#define MXX 100500
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
int seg[MXX], buf[MXX], val[MXX], id[MXX], ans[MX];
int blk[330][330], cnt[330];
int siz, n, m, dif;
struct Query {int lef, rig, lb, rb, id;} que[MX];
IN bool operator < (const Query &x, const Query &y)
{
if (seg[x.lef] ^ seg[y.lef]) return seg[x.lef] < seg[y.lef];
return (seg[x.lef] & 1) ? seg[x.rig] < seg[y.rig] : seg[x.rig] > seg[y.rig];
}
IN void insert(R int v)
{
int bk = (v - 1) / siz + 1, pos = v - (bk - 1) * siz;
if (!blk[bk][pos]) ++cnt[bk];
blk[bk][pos]++;
}
IN void erase(R int v)
{
int bk = (v - 1) / siz + 1, pos = v - (bk - 1) * siz;
if (blk[bk][pos] == 1) --cnt[bk];
blk[bk][pos]--;
}
IN int query(R int lb, R int rb)
{
if (lb > rb) return 0; --lb;
int bk = lb / siz, ret = 0, bd = lb - bk * siz, nex = bk + 1;
for (R int i = 1; i <= bk; ++i) ret -= cnt[i];
for (R int i = 1; i <= bd; ++i) ret -= (blk[nex][i] > 0);
bk = rb / siz, bd = rb - bk * siz, nex = bk + 1;
for (R int i = 1; i <= bk; ++i) ret += cnt[i];
for (R int i = 1; i <= bd; ++i) ret += (blk[nex][i] > 0);
return ret;
}
int main(void)
{
in(n), in(m); int ql, qr, SIZ = std::sqrt(n);
for (R int i = 1; i <= n; ++i) seg[i] = (i - 1) / SIZ + 1;
for (R int i = 1; i <= n; ++i) in(val[i]), buf[i] = val[i];
std::sort(buf + 1, buf + 1 + n);
dif = std::unique(buf + 1, buf + 1 + n) - buf - 1;
siz = std::sqrt(dif);
for (R int i = 1; i <= n; ++i) id[i] = std::lower_bound(buf + 1, buf + dif + 1, val[i]) - buf;
for (R int i = 1; i <= m; ++i)
in(que[i].lef), in(que[i].rig), in(que[i].lb), in(que[i].rb), que[i].id = i;
std::sort(que + 1, que + 1 + m);
R int l = que[1].lef, r = que[1].rig;
for (R int i = que[1].lef; i <= que[1].rig; ++i) insert(id[i]);
ql = std::lower_bound(buf + 1, buf + 1 + dif, que[1].lb) - buf;
qr = std::lower_bound(buf + 1, buf + 1 + dif, que[1].rb) - buf;
if (ql > dif) goto jp;
if (qr > dif) --qr;
if (buf[qr] > que[1].rb) --qr;
ans[que[1].id] = query(ql, qr);
jp :;
for (R int i = 2; i <= m; ++i)
{
W (l > que[i].lef) insert(id[--l]);
W (l < que[i].lef) erase(id[l++]);
W (r > que[i].rig) erase(id[r--]);
W (r < que[i].rig) insert(id[++r]);
ql = std::lower_bound(buf + 1, buf + 1 + dif, que[i].lb) - buf;
qr = std::lower_bound(buf + 1, buf + 1 + dif, que[i].rb) - buf;
if (ql > dif) continue;
if (qr > dif) --qr;
if (buf[qr] > que[i].rb) --qr;
ans[que[i].id] = query(ql, qr);
}
for (R int i = 1; i <= m; ++i) printf("%d\n", ans[i]);
}