Codeforces 85 D. Sum of Medians
問題
集合S={a1,a2,..,ak}に対して、Sのsum of Mediansとは、
Σ[i≦k かつ i mod 5 = 3]a[i]により定義される。
最初集合Sは空である。
次のn個のクエリが与えられるので、それらに答えよ。
- add x 集合Sにxを加える。この操作の時点でSにxは存在しない。
- del x 集合Sからxを削除する。この操作の時点でSにxは含まれている。
- sum 集合Sのsum of Mediansを出力する。
制約条件
n≦10^5
xは正の整数かつx≦10^9
方針
平方分割でやったら意味不明なWAがとれなかった。
多分平方分割でも出来るはず。
Segment Treeを使った解法は以下の通り。
最初にxの値を全部列挙しておき、座標圧縮した後で、Segment Treeを2つ作る。
sum[p][i]に、pに対応する区間のうち、区間の左から数えてmod 5でi番目のものを取り出したときの和を持たせる。
cnt[p]に、pに対応する区間に含まれる数の個数を持たせる。
クエリが来たとき、sumはsum[0][2]を出力すればよい。
add来たら、xに対応する区間木の葉のノードをsum[p][0]=xに書き換え、cnt[p]=1に書き換えて、その頂点から根までを更新する。
delが来たら、xに対応する区間木の葉のノードをsum[p][0]=0に書き換え、cnt[p]=0に書き換えて、その頂点から根までを更新する。
更新は、sum[k][i]=sum[k*2+1][i]+sum[k*2+2][iを左の区間に含まれる数mod 5だけずらした値]とすればよい。
ソースコード
const int N=1<<17; int n; ll sum[2*N-1][5]; int cnt[2*N-1]; vector<pi> qs; void update(int k){ cnt[k]=cnt[k*2+1]+cnt[k*2+2]; rep(i,5)sum[k][i]=sum[k*2+1][i]+sum[k*2+2][(i-cnt[k*2+1]%5+5)%5]; } void run() { cin>>n; map<int,int> M; int k=0; rep(i,n){ int x; string q; cin>>q; if(q=="sum")qs.pb(mp(2,0)); else{ cin>>x; qs.pb(mp(q=="add",x)); M[x]=0; } } fr(i,M)i->second=k++; rep(i,n){ int t=qs[i].first, x=qs[i].second; if(t==2)cout<<sum[0][2]<<endl; else{ int p=M[x]+N-1; cnt[p]=t; sum[p][0]=t*x; for(p=(p-1)/2;;p=(p-1)/2){ update(p); if(p==0)break; } } } }