TIOJ-1922

給一個長度為$N$的序列

$Q$筆詢問,每次給定$L,R$,定義$cnt_x$為$[L, R)$中$x$的出現次數

回答$\sum cnt_x^2\times x$。

$1\le N\le 4\times 10^4, 1\le Q\le 4\times 10^5$


第一次看到這題完全沒想法@@,被捏了才知道。
因為需要的參數為出現次數,所以可以直接砸墨隊。
然後就是很標準的墨隊實作了。
複雜度的部分,原本我是取每塊大小為$\sqrt{N}$,這樣複雜度是$\mathcal{O}(Q\sqrt N)$,這題$Q$比$N$大很多,會吃TLE吃到爽。

每塊大小改取$\frac{Q}{\sqrt N}$,複雜度變為$\mathcal{O}(N\sqrt Q)$,就能好好ac了(不過用vector還是會tle幾筆,得改成一般陣列)。

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
#include <bits/stdc++.h>
using namespace std;

#define EmiliaMyWife ios::sync_with_stdio(0); cin.tie(NULL);
/*-----------------------------------------------------------------------------------------------------*/

struct query {
int l, r, b, id;
friend bool operator<(const query &a, const query &b) {
return a.b == b.b ? ((a.r > b.r) ^ (a.b & 1)) : a.b < b.b;
}
};

const int N = 4e4 + 25, Q = 4e5 + 25;
int arr[N], ans[Q], cnt[N], v[N];
query que[Q];

signed main() { EmiliaMyWife
int n, q;
cin >> n >> q;
int sz = int(n / sqrt(q)) + 1, cur = 0;
auto get = [&] (int x) {
return 1LL * cnt[x] * cnt[x] % MOD * v[x] % MOD;
};
auto add = [&] (int x) {
cur = (cur - get(x) + MOD) % MOD;
cnt[x]++;
cur = (cur + get(x)) % MOD;
};
auto sub = [&] (int x) {
cur = (cur - get(x) + MOD) % MOD;
cnt[x]--;
cur = (cur + get(x)) % MOD;
};

for(int i = 0; i < n; i++)
cin >> arr[i], v[i] = arr[i];
sort(v, v + n);
auto v_end = unique(v, v + n);
for(auto &x : arr)
x = lower_bound(v, v_end, x) - v;
for(int i = 0; i < q; i++) {
cin >> que[i].l >> que[i].r;
que[i].r--;
que[i].b = que[i].l / sz;
que[i].id = i;
}
int l = 0, r = -1;
sort(que, que + q);
for(int i = 0; i < q; i++) {
const auto &x = que[i];
while(r < x.r)
add(arr[++r]);
while(l > x.l)
add(arr[--l]);
while(r > x.r)
sub(arr[r--]);
while(l < x.l)
sub(arr[l++]);
ans[x.id] = cur;
}
for(int i = 0; i < q; i++)
cout << ans[i] << '\n';
}