給一個長度為$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'; }
   |