Codeforces 86 D. Powerful array
問題
n項の数列が与えられる。
この数列に対してt個のクエリに答えよ。
クエリ:
整数l,rに対して、次の値を求める。
a[l],a[l+1],...,a[r]における、値sの出現回数をKsとする。
全ての整数sについて、Σs*Ks*ks
制約条件
n,t≦200000
1≦a[i]≦10^6
方針
クエリを並べ替えて処理する。
平方分割っぽいことをする。
lが近いクエリを集めて、rの順にソートすれば、
値の出現回数を求める処理(差分により計算する)はほとんど同じになって計算量が減る。
具体的には(l/500,r)でクエリをソートして処理すればいい。
ソースコード
int n,t,a[200000],le[200000],ri[200000]; pair<pair<int,int>,int> q[200000]; int cnt[1000001]; ll ans[200000]; void run(){ scanf("%d%d",&n,&t); rep(i,n)scanf("%d",a+i); rep(i,t){ int l,r; scanf("%d%d",le+i,ri+i); q[i]=make_pair(make_pair(--le[i]/500,ri[i]),i); } sort(q,q+t); int l=0,r=0; ll sum=0; rep(i,t){ int pos=q[i].second, L=le[pos], R=ri[pos]; while(l<L){ sum-=cnt[a[l]]*(ll)cnt[a[l]]--*a[l]; sum+=cnt[a[l]]*(ll)cnt[a[l]]*a[l++]; } while(l>L){ sum-=cnt[a[--l]]*(ll)cnt[a[l]]++*a[l]; sum+=cnt[a[l]]*(ll)cnt[a[l]]*a[l]; } while(r<R){ sum-=cnt[a[r]]*(ll)cnt[a[r]]++*a[r]; sum+=cnt[a[r]]*(ll)cnt[a[r]]*a[r++]; } while(r>R){ sum-=cnt[a[--r]]*(ll)cnt[a[r]]--*a[r]; sum+=cnt[a[r]]*(ll)cnt[a[r]]*a[r]; } ans[pos]=sum; } rep(i,t)cout<<ans[i]<<endl; }