Processing math: 90%
Solutions of Range query - MarisaOJ: Marisa Online Judge

Solutions of Range query

Select solution language

Write solution here.


bean    Created at    9 likes

Dễ dàng nhận thấy rằng ta có thể dùng thuật toán Mo's và Fenwick tree hoặc Segment tree để giải bài toán này trong O((n+q)nlogn) Vậy thì làm thế nào để ta có thể tối ưu nó hơn? Gọi freq(i) là tần số xuất hiện của phần tử i trong đoạn ta đang xét, ta cũng có thể dễ dàng tính mảng distinct(i) là số phần tử có freq(i)>0. Ta có thể tính nhanh bằng cách dịch đoạn bằng Mo's với mỗi truy vấn trong O(B) Vậy vấn đề cuối cùng ở đây là làm sao để tính nhanh số phần tử có trong đoạn / số phần tử phân biệt? Ta có thể chia mảng freqdistinct ra thành B đoạn. Gọi f(i) là tổng của freq(j), và d(i) là tổng của distinct(j) với j[iB,(i+1)B) Sau khi xử lý xong, với mỗi truy vấn, ta chỉ đơn giản là xét các đoạn i sao cho [iB,(i+1)B)[a,b] và xử lý đoạn không nằm trong hoàn toàn riêng. Khi ta chọn độ dài của đoạn B=n thì tổng độ phức tạp sẽ là O((n+q)2n) Code tham khảo: cpp#cludebits/stdc++.husingnamespacestd;constN=1e5;constsqr=320;structQuery{l,r,a,b,;pair<,>Pair()const{blk=lsqr;return{blk,blk&1?-r:r};}bloperar<(constQuery&other){returnPair()<other.Pair();}};ma(){c.tie(0)syncwithstdio(0);n,q;cnq;r<>v(n);for(i=0;i<n;i++){cv[i];}array<,N+1>eq{};array<r<>,2>cnt;cnt[0]=cnt[1]=r<>(Nsqr+1);auadd=[&](x){blk=xsqr;cnt[0][blk]++;cnt[1][blk]+=(eq[x]==0);eq[x]++;};au=[&](x){blk=xsqr;cnt[0][blk]--;cnt[1][blk](eq[x]==1);eq[x]--;};r<Query>queries(q);for(i=0;i<q;i++){l,r,a,b;clrab;--l;--r;queries[i]={l,r,a,b,i};}sort(queries.beg(),queries.end());r<pair<,ans(q);curl=0,curr=-1;for(Query&qr:queries){whi(curl>qr.l)add(v[--curl]);whi(curr<qr.r)add(v[++curr]);whi(curl<qr.l)(v[curl++]);whi(curr>qr.r)(v[curr--]);au&[u,v]=ans[qr.id