문제: icpc.me/8462
시퀀스와 쿼리가 주어질 때 매 쿼리에 대한 답을 출력하는 문제이다.
쿼리는 구간이 주어지면 구간에 존재하는 모든 자연수 s에 대하여 (s 의 개수의 제곱) x s를 합한 값이다.
쿼리와 시퀀스가 10만이기 때문에 적어도 쿼리를 log나 root 시간에 처리해주고 싶지만 안타깝게도 저 쿼리를 해당 시간에 처리하기는 힘든거 같다.
하지만 쿼리 도중에 업데이트가 일어나지 않기 때문에 쿼리를 정렬한 뒤 mo's 알고리즘으로 접근한다면 해답을 얻을 수 있다.
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 | #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; ll n, m, a[100010], sz, cnt[1000010], curr, ans[100010]; struct qry { ll lo, hi, idx; qry(ll lo, ll hi, ll idx) :lo(lo), hi(hi), idx(idx) {}; qry() {} bool operator<(const qry& x){ ll lidx = hi / sz; ll ridx = x.hi / sz; return lidx == ridx ? lo < x.lo : lidx < ridx; } }q[100010]; void add(ll num) { curr -= cnt[num] * cnt[num] * num; cnt[num]++; curr += cnt[num] * cnt[num] * num; } void erase(ll num) { curr -= cnt[num] * cnt[num] * num; cnt[num]--; curr += cnt[num] * cnt[num] * num; } int main() { scanf("%d%d", &n, &m); sz = sqrt(n); for (int i = 0; i < n; i++) scanf("%d", &a[i]); for (int i = 0; i < m; i++) { ll x, y; scanf("%lld%lld", &x, &y); q[i] = qry(x - 1, y - 1, i); } sort(q, q + m); ll lo = 0, hi = 0; add(a[0]); for (int i = 0; i < m;i++) { auto &next = q[i]; ll nlo = next.lo, nhi = next.hi; for (int i = lo; i < nlo; i++) erase(a[i]); for (int i = lo - 1; i >= nlo; i--) add(a[i]); for (int i = hi + 1; i <= nhi; i++) add(a[i]); for (int i = hi; i > nhi; i--) erase(a[i]); lo = nlo; hi = nhi; ans[next.idx] = curr; } for (int i = 0; i < m; i++) printf("%lld\n", ans[i]); return 0; } | cs |
'알고리즘 관련 > BOJ' 카테고리의 다른 글
BOJ)2872 우리집엔 도서관이 있어 (0) | 2017.08.20 |
---|---|
BOJ)10272 현상금 사냥꾼 김정은 (1) | 2017.08.19 |
BOJ)3172 현주와 윤주의 재미있는 단어 게임 (0) | 2017.08.15 |
BOJ)14675 단절점과 단절선 (1) | 2017.08.06 |
BOJ)14426 접두사 찾기 (0) | 2017.08.04 |