rangereport(l,r,x,y) : 数列の区間[l,r)に含まれるx以上y未満の要素を列挙する
rangemink(l,r,k) : 数列の区間[l,r)に含まれる要素のうち 小さい方 からk個を列挙する
rangemaxk(l,r,k) : 数列の区間[l,r)に含まれる要素のうち 大きい方 からk個を列挙する
静的WM(ウェーブレット行列)によるrangereportの処理の手順はおおよそ次のようになる
report_me(i,l,r,x) : WMのi行の区間[l,r)に含まれる x以上 の要素を列挙する
report_lt(i,l,r,x) : WMのi行の区間[l,r)に含まれる x未満 の要素を列挙する
report_all(i,l,r) : WMのi行の区間[l,r)に含まれる 全 て の要素を列挙する
x<yとする
WMの最初の行から開始し、xとyのビットが等しい間はWM上をその方向に進む
xが0、yが1になる最初のビットの行の次の行の0側に対してreport_meを呼びx以上を列挙し、1側に対してreport_ltを呼びy未満を列挙する
(最初の行が最後の行のとき((x+1=y かつ xは偶数)のとき)はxを最後の行のビットベクトルの[l,r)に含まれる0の数だけ出力して終了)
report_me、report_lt内で必要があればreport_allを呼ぶ
WMは上位ビットからの基数ソートによって構築されるが、基数ソートを行うときに使用する作業用配列を書き換えずに全て保存したものがこの場合の補助データになる
msb : 要素の最大値の最上位の1のビットの位置(1桁目を0-thビットとする)
w(msb) : 対象となる数列そのもの
w(i) : w(i+1)の要素を(i+1)-thビットをキーにしてソートした数列
のとき0≦i≦msbのw(i)を保存するということ
静的な場合、mを要素の最大値、kをrangereportの解の個数とするとrangereportをWMだけで行うとO(log(m)*k)であるが、補助データを使うとi行にいるときのreport_all(i,l,r)がO(r-l)になるためO(log(m)+k)になる
動的な場合、nを入力件数とするとrangereportをWMだけで行うとO(log(m)*log(n)*k)であるが、静的な場合の補助データを平衡木によって実現するとreport_allがO(log(n)+r-l)になるためO(log(m)*log(n)+k)になる
rangeminkとrangemaxkは探索過程で解として確定した要素はreport_allで列挙し確定していない要素は次の行以降で探索するというようにするとrangereportと同じ計算量になる(こちらのkは引数で指定される定数であるという違いはある)
rangepreport_posのように処理名に_posがついているものは値を列挙するだけでなく値の数列上の位置を返す処理でありO(log(m)*log(n)*k)である
(この計算量は補助データを使わないWMと等しいがメモリ使用量の定数倍の増大によってO(log(m)*log(n)+log(n)*k)に改善できる)
その他
上の説明は1ビット単位での基数ソートによるWMなので32ビットデータを扱う場合補助データとして静的な場合は32本の配列、動的な場合は32本の平衡木を使用する必要があるがこれがメモリ的に問題になる場合は4ビットや8ビット単位での基数ソートによるWMに変更すると使用する配列や平衡木の本数を減らすことができる
補助データをWM(補助データを使う)で構築するという高次元化が理屈上は可能であるが実用上はメモリの制約のため低次元でしか動かせない(Range Treeなどの高次元化に伴う問題と同様である)
WMは何がうれしいのか
静的な構造を自然な拡張によって動的な構造に変換してもならし計算量にならないところ
重み付きインターバルデータに対するTop-k範囲探索
これは少し前に何かで検索してたら見つけた問題でrangereportが使えないかなどと考えていたらクエリO(log(N)+k)になる気がしたのでいつかコードとかを書くかもしれない
#include
#include
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
void qs2(uint *a,uint *b,uint n_,uint *w){
if (!n_) return;
uint l,r,l_,r_,m,t,sp=0;
l_=0;r_=n_-1;
while (1){
l=l_;r=r_;
m=a[(l+r)>>1];
while (l<=r){
while (a[l]<m) ++l;
while (m<a[r]) --r;
if (l<=r){
t=a[l],a[l]=a[r],a[r]=t;
t=b[l],b[l]=b[r],b[r]=t;
++l;
if (r) --r; }
}
if (l_+1<l){
if (l<r_) w[sp]=l,w[sp+1]=r_,sp+=2;
r_=l-1;
}else if (l<r_){
l_=l;
}else if (sp){
r_=w[--sp];l_=w[--sp];
}else{
break;
}
}
}
void qs_k(uint *a,uint k,uint n_){
if (k>=n_) return;
uint l,r,l_,r_,m,t;
l_=0;r_=n_-1;
while (1){
l=l_;
r=r_;
m=a[(l+r)>>1];
while (l<=r){
while (a[l]<m) ++l;
while (m<a[r]) --r;
if (l<=r){
t=a[l],a[l]=a[r],a[r]=t;
++l;
if (r) --r;
}
}
if (k>1;
m=a[t];
i=ix[t];
while (l<=r){
while (a[l]>SH)&255];
}
}
uint array_sum(uint *p,uint n_){
uint s=0;
for (uint i=0;i<n_;++i) s+=p[i];
return s;
}
uint node_split(uint ib,uint newi,uint internalnode){
if (internalnode){
uint t=M/2;
memcpy(b[newi].a,b[ib].a+t,t*4);
memcpy(b[newi].b,b[ib].b+t,t*4);
b[ib].n=b[newi].n=t;
split_c(ib,newi);
return array_sum(b[newi].b,t);
}else{
uint t=leafsize/2;
memcpy(bl[newi].a,bl[ib].a+t,t*szx);
bl[ib].n=bl[newi].n=t;
bl[newi].pleaf=bl[ib].pleaf;bl[ib].pleaf=newi;
return t;
}
}
uint node_merge(uint lb,uint ib,uint internalnode){
if (internalnode){
uint t=b[lb].n;
uint u=b[ib].n;
memcpy(b[lb].a+t,b[ib].a,u*4);
memcpy(b[lb].b+t,b[ib].b,u*4);
merge_c(lb,ib);
b[lb].n+=u;
return array_sum(b[lb].b,t+u);
}else{
uint t=bl[lb].n;
uint u=bl[ib].n;
memcpy(bl[lb].a+t,bl[ib].a,u*szx);
bl[lb].n+=u;
bl[lb].pleaf=bl[ib].pleaf;
return t+u;
}
}
void c_popr_shiftr(uint ib,uint l,uint r){
if (l<r){
uint *p=b[ib].c+l*256;
memmove(p+256,p,(r-l)*256*4);
}
}
void c_popl_shiftl(uint ib,uint l,uint r){
if (l<r){
uint *p=b[ib].c+l*256;
memmove(p,p+256,(r-l)*256*4);
}
}
void c_count_leaf(uint ib,uint n_,uint *ans,uint init=0){
uint *p=bl[ib].a;
const uint s=SH;
if (init) memset(ans,0,256*4);
for (uint i=0;i<n_;++i) ++ans[(p[i]>>s)&255];
}
uint leaf_rank(uint *p,uint n_,uint x,uint ms){
uint s=0;
for (;n_;--n_,++p){
if ((*p&ms)==x) ++s;
}
return s;
}
void c_add_c(uint *c,uint *c2){
for (uint i=0;i<256;++i) c[i]+=c2[i];
}
void c_sub_c(uint *c,uint *c2){
for (uint i=0;i<256;++i) c[i]-=c2[i];
}
void cs_add_c(uint ib,uint i,uint n_){
uint *p=b[ib].c+i*256;
for (uint *q=p+256;0<n_;--n_,q+=256){
for (uint k=0;k<256;++k) q[k]+=p[k];
}
}
void cs_sub_c(uint ib,uint i,uint n_){
uint *p=b[ib].c+i*256;
for (uint *q=p+256;0<n_;--n_,q+=256){
for (uint k=0;k<256;++k) q[k]-=p[k];
}
}
void split_c(uint ib,uint rb){
cs_sub_c(ib,M/2-1,M/2);
memcpy(b[rb].c,b[ib].c+(M/2)*256,(M/2)*256*4);
}
void merge_c(uint ib,uint rb){
uint nl=b[ib].n;
uint nr=b[rb].n;
memcpy(b[ib].c+nl*256,b[rb].c,nr*256*4);
cs_add_c(ib,nl-1,nr);
}
void insert_c(uint ib,uint pos,uint internalnode){
uint ic,*p,*q;
ic=b[ib].a[pos];
c_popr_shiftr(ib,pos,b[ib].n);
p=b[ib].c+pos*256;
if (internalnode-1){
q=b[ic].c+((M/2-1)*256);
memcpy(p,q,256*4);
if (pos) c_add_c(p,p-256);
}else{
if (pos) memcpy(p,p-256,256*4);
c_count_leaf(ic,leafsize/2,p,!pos);
}
}
void remove_c(uint ib,uint pos){
uint *p=b[ib].c+pos*256;
memmove(p,p+256,(b[ib].n-(pos+1))*256*4);
}
uint insert2_rnk(uint ib,uint k,uint x,uint ip,uint retrank){
uint t,pos,ic,*p,*q,h,ret,s=0;
const uint y=(x>>SH)&255;
for (h=hi;1<h;--h){
b[ib].ip=ip;
p=b[ib].b;
for (pos=0;p[pos]<k;++pos) k-=p[pos];
++p[pos];
b[ib].pos=pos;
ic=b[ib].a[pos];
p=q=b[ib].c+(pos*256+y);
if (pos) s+=q[-256];
for (t=b[ib].n-pos;t;q+=256,--t) ++*q;
ip=ib;
ib=ic;
}
q=bl[ib].a;
if (retrank){
if (k+k<=bl[ib].n || ip==UINT_MAX){
s+=leaf_rank(q,k,x&MS,MS);
}else{
s+=pos? (*p-p[-256])-1:*p-1;
s-=leaf_rank(q+k,bl[ib].n-k,x&MS,MS);
}
Trank=s;
}
memmove(q+(k+1),q+k,(bl[ib].n-k)*szx);
bl[ib].a[k]=x;
ret=(++bl[ib].n==leafsize);
for (ic=ib,ib=ip;ret && ib!=UINT_MAX;++h){
uint newi=getindex(h-1);
pos=b[ib].pos;
insert_c(ib,pos,h);
t=node_split(ic,newi,h-1);
b[ib].b[pos]-=t;
ret=finsert(ib,pos+1,newi,t);
ic=ib;
ib=b[ib].ip;
}
return ret;
}
uint remove2_rnk(uint ib,uint k,uint ip,uint retrank){
uint t,pos,ic,*p,*q,rc,h,ret,x,s=0;
for (h=hi;1<h;--h){
b[ib].ip=ip;
p=b[ib].b;
for (pos=0;k>=p[pos];++pos) k-=p[pos];
--p[pos];
b[ib].pos=pos;
p=b[ib].c+pos*256;
ip=ib;
ib=b[ib].a[pos];
}
q=bl[ib].a;
t=Tx=q[k];
x=(t>>SH)&255;
if (retrank){
if (k+k<=bl[ib].n || ip==UINT_MAX){
s=leaf_rank(q,k,t&MS,MS);
}else{
p+=x;
s=pos? (*p-p[-256])-1:*p-1;
s-=leaf_rank(q+(k+1),bl[ib].n-(k+1),t&MS,MS);
}
}
t=--bl[ib].n-k;
memmove(q+k,q+(k+1),t*szx);
ret=(bl[ib].n<crem_l);
for (ic=ib,ib=ip;ib!=UINT_MAX;++h){
pos=b[ib].pos;
q=b[ib].c+(pos*256+x);
if (pos) s+=q[-256];
for (t=b[ib].n-pos;t;q+=256,--t) --*q;
if (ret){
if (pos+1<b[ib].n){
rc=b[ib].a[pos+1];
ret=(h-1)? b[rc].n<=crem:bl[rc].n<=crem_l;
if (!ret) underflow(ib,pos,h);
}else{
rc=ic;
ic=b[ib].a[--pos];
ret=(h-1)? (b[ic].n+b[rc].n<crem*2 || !b[rc].n):(bl[ic].n+bl[rc].n<crem_l*2 || !bl[rc].n);
}
if (ret){
remove_c(ib,pos);
b[ib].b[pos]=node_merge(ic,rc,h-1);
putindex(rc,h-1);
ret=fremove(ib,pos+1);
}
}
ic=ib;
ib=b[ib].ip;
}
Trank=s;
return ret;
}
void freq(uint **P,uint **Q,uint pq,uint *ans){
uint i,*p0,*p1,*p2,*p3,*p4,*p5,*p6,*q0,*q1,*q2,*q3,*q4,*q5,*q6;
switch (pq){
case 1:
// q0=Q[0];
// for (i=0;i<256;++i) ans[i]=-q0[i];break;
case 10:
p0=P[0];
for (i=0;i<256;++i) ans[i]=p0[i];break;
case 11:
p0=P[0],q0=Q[0];
for (i=0;i<256;++i) ans[i]=p0[i]-(q0[i]);break;
case 12:
p0=P[0],q0=Q[0],q1=Q[1];
for (i=0;i<256;++i) ans[i]=p0[i]-(q0[i]+q1[i]);break;
case 13:
p0=P[0],q0=Q[0],q1=Q[1],q2=Q[2];
for (i=0;i<256;++i) ans[i]=p0[i]-(q0[i]+q1[i]+q2[i]);break;
case 14:
p0=P[0],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3];
for (i=0;i<256;++i) ans[i]=p0[i]-(q0[i]+q1[i]+q2[i]+q3[i]);break;
case 15:
p0=P[0],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4];
for (i=0;i<256;++i) ans[i]=p0[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]);break;
case 16:
p0=P[0],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5];
for (i=0;i<256;++i) ans[i]=p0[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]);break;
case 17:
p0=P[0],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5],q6=Q[6];
for (i=0;i<256;++i) ans[i]=p0[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]+q6[i]);break;
case 20:
p0=P[0],p1=P[1];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i];break;
case 21:
p0=P[0],p1=P[1],q0=Q[0];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]-(q0[i]);break;
case 22:
p0=P[0],p1=P[1],q0=Q[0],q1=Q[1];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]-(q0[i]+q1[i]);break;
case 23:
p0=P[0],p1=P[1],q0=Q[0],q1=Q[1],q2=Q[2];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]-(q0[i]+q1[i]+q2[i]);break;
case 24:
p0=P[0],p1=P[1],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]-(q0[i]+q1[i]+q2[i]+q3[i]);break;
case 25:
p0=P[0],p1=P[1],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]);break;
case 26:
p0=P[0],p1=P[1],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]);break;
case 27:
p0=P[0],p1=P[1],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5],q6=Q[6];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]+q6[i]);break;
case 30:
p0=P[0],p1=P[1],p2=P[2];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i];break;
case 31:
p0=P[0],p1=P[1],p2=P[2],q0=Q[0];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]-(q0[i]);break;
case 32:
p0=P[0],p1=P[1],p2=P[2],q0=Q[0],q1=Q[1];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]-(q0[i]+q1[i]);break;
case 33:
p0=P[0],p1=P[1],p2=P[2],q0=Q[0],q1=Q[1],q2=Q[2];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]-(q0[i]+q1[i]+q2[i]);break;
case 34:
p0=P[0],p1=P[1],p2=P[2],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]-(q0[i]+q1[i]+q2[i]+q3[i]);break;
case 35:
p0=P[0],p1=P[1],p2=P[2],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]);break;
case 36:
p0=P[0],p1=P[1],p2=P[2],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]);break;
case 37:
p0=P[0],p1=P[1],p2=P[2],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5],q6=Q[6];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]+q6[i]);break;
case 40:
p0=P[0],p1=P[1],p2=P[2],p3=P[3];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i];break;
case 41:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],q0=Q[0];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]-(q0[i]);break;
case 42:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],q0=Q[0],q1=Q[1];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]-(q0[i]+q1[i]);break;
case 43:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],q0=Q[0],q1=Q[1],q2=Q[2];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]-(q0[i]+q1[i]+q2[i]);break;
case 44:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]-(q0[i]+q1[i]+q2[i]+q3[i]);break;
case 45:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]);break;
case 46:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]);break;
case 47:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5],q6=Q[6];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]+q6[i]);break;
case 50:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i];break;
case 51:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],q0=Q[0];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]-(q0[i]);break;
case 52:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],q0=Q[0],q1=Q[1];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]-(q0[i]+q1[i]);break;
case 53:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],q0=Q[0],q1=Q[1],q2=Q[2];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]-(q0[i]+q1[i]+q2[i]);break;
case 54:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]-(q0[i]+q1[i]+q2[i]+q3[i]);break;
case 55:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]);break;
case 56:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]);break;
case 57:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5],q6=Q[6];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]+q6[i]);break;
case 60:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i];break;
case 61:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],q0=Q[0];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]-(q0[i]);break;
case 62:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],q0=Q[0],q1=Q[1];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]-(q0[i]+q1[i]);break;
case 63:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],q0=Q[0],q1=Q[1],q2=Q[2];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]-(q0[i]+q1[i]+q2[i]);break;
case 64:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]-(q0[i]+q1[i]+q2[i]+q3[i]);break;
case 65:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]);break;
case 66:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]);break;
case 67:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5],q6=Q[6];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]+q6[i]);break;
case 70:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],p6=P[6];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]+p6[i];break;
case 71:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],p6=P[6],q0=Q[0];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]+p6[i]-(q0[i]);break;
case 72:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],p6=P[6],q0=Q[0],q1=Q[1];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]+p6[i]-(q0[i]+q1[i]);break;
case 73:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],p6=P[6],q0=Q[0],q1=Q[1],q2=Q[2];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]+p6[i]-(q0[i]+q1[i]+q2[i]);break;
case 74:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],p6=P[6],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]+p6[i]-(q0[i]+q1[i]+q2[i]+q3[i]);break;
case 75:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],p6=P[6],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]+p6[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]);break;
case 76:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],p6=P[6],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]+p6[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]);break;
case 77:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],p6=P[6],q0=Q[0],q1=Q[1],q2=Q[2],q3=Q[3],q4=Q[4],q5=Q[5],q6=Q[6];
for (i=0;i<256;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]+p6[i]-(q0[i]+q1[i]+q2[i]+q3[i]+q4[i]+q5[i]+q6[i]);break;
}
}
void freq1(uint **P,uint p,uint *ans,const uint i0,const uint i1){
uint i,*p0,*p1,*p2,*p3,*p4,*p5,*p6;
switch (p){
case 1:
p0=P[0];
for (i=i0;i<i1;++i) ans[i]=p0[i];break;
case 2:
p0=P[0],p1=P[1];
for (i=i0;i<i1;++i) ans[i]=p0[i]+p1[i];break;
case 3:
p0=P[0],p1=P[1],p2=P[2];
for (i=i0;i<i1;++i) ans[i]=p0[i]+p1[i]+p2[i];break;
case 4:
p0=P[0],p1=P[1],p2=P[2],p3=P[3];
for (i=i0;i<i1;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i];break;
case 5:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4];
for (i=i0;i<i1;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i];break;
case 6:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5];
for (i=i0;i<i1;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i];break;
case 7:
p0=P[0],p1=P[1],p2=P[2],p3=P[3],p4=P[4],p5=P[5],p6=P[6];
for (i=i0;i<i1;++i) ans[i]=p0[i]+p1[i]+p2[i]+p3[i]+p4[i]+p5[i]+p6[i];break;
}
}
void ini2(uint il,uint n_,uint h_){
uint i,j,k,ib,ul=mi;
for (i=n_;i;i-=k){
ib=mi++;
k=(M/2<=i)? M/2:i;
b[ib].n=k;
for (j=0;j<k;++j,++il){
b[ib].a[j]=il;
b[ib].b[j]=(1<h_)? array_sum(b[il].b,b[il].n):bl[il].n;
}
}
if (ul+1>SH)&255))>>4];
if (bl[root].n==(leafsize/2)) ++root;
bl[root].a[bl[root].n]=x;
++bl[root].n;
}
void init2(uint i,uint x){
uint j=i>>8;
++memi[((x>>SH)&255)>>4];
bl[j].a[i&255]=x;
++bl[j].n;
if (root<j) root=j;
}
uint init_access_x(uint i){
return bl[i>>8].a[i&255];
}
void init_end(){
if (root && bl[root].n<crem_l){
memcpy(bl[root-1].a+bl[root-1].n,bl[root].a,bl[root].n*szx);
bl[root-1].n+=bl[root].n;
--root;
}
mi_l=root+1;
if (root){
for (uint i=0;i<root;++i) bl[i].pleaf=i+1;
ini2(0,root+1,1);
ini3(root,NULL,hi);
}
}
uint access(uint k){
uint *p,pos,ib=root;
for (uint h=hi;1<h;--h){
p=b[ib].b;
for (pos=0;k>=p[pos];++pos) k-=p[pos];
ib=b[ib].a[pos];
}
return bl[ib].a[k];
}
uint insert_rank(uint k,uint x,uint retrank){
++memi[(x>>(SH+4))&15];
if (insert2_rnk(root,k,x,UINT_MAX,retrank)){
uint ro=getindex(1);
uint r=getindex(hi-1);
b[ro].a[0]=root;
b[ro].a[1]=r;
if (1<hi){
memcpy(b[ro].c,b[root].c+((M/2-1)*256),256*4);
memcpy(b[ro].c+256,b[root].c+((M-1)*256),256*4);
b[ro].b[0]=array_sum(b[root].b,M/2);
b[ro].b[1]=node_split(root,r,1);
}else{
node_split(root,r,0);
c_count_leaf(root,leafsize/2,b[ro].c,1);
memcpy(b[ro].c+256,b[ro].c,256*4);
c_count_leaf(r,leafsize/2,b[ro].c+256);
b[ro].b[0]=b[ro].b[1]=leafsize/2;
}
b[ro].n=2;
root=ro;
++hi;
}
return Trank;
}
uint remove_rank(uint k,uint retrank){
if (remove2_rnk(root,k,UINT_MAX,retrank) && 1>(SH+4))&15];
return Trank;
}
uint removed_x(){
return Tx;
}
void frequency(uint l,uint r,uint *ans){
uint i,pos,pos2,*p,*q,ib,ib2,np,nq,d,d2;
uint **P=ps;
uint **Q=qs;
const uint s=SH;
ib=ib2=root;
np=nq=d=d2=0;
for (i=hi;1<i;--i){
q=b[ib2].b;
for (pos2=0;q[pos2]<l;++pos2) l-=q[pos2];
if (pos2) Q[nq++]=b[ib2].c+(pos2-1)*256;
else Q[nq]=b[ib2].c;
ib2=b[ib2].a[pos2];
p=b[ib].b;
for (pos=0;p[pos]<r;++pos) r-=p[pos];
if (pos) P[np++]=b[ib].c+(pos-1)*256;
else P[np]=b[ib].c;
ib=b[ib].a[pos];
if (ib==ib2 && pos) --np,--nq;
}
if (np){
if (q[pos2]<l+l){
if (pos2) Q[nq-1]+=256;
else ++nq;
d2=1;
}
if (p[pos]<r+r){
if (pos) P[np-1]+=256;
else ++np;
d=1;
}
freq(P,Q,np*10+nq,ans);
if (d==0){
for (uint *u=bl[ib].a;r;++u,--r) ++ans[(*u>>s)&255];
}else{
i=bl[ib].n-r;
for (uint *u=bl[ib].a+r;i;++u,--i) --ans[(*u>>s)&255];
}
if (d2==0){
for (uint *u=bl[ib2].a;l;++u,--l) --ans[(*u>>s)&255];
}else{
i=bl[ib2].n-l;
for (uint *u=bl[ib2].a+l;i;++u,--i) ++ans[(*u>>s)&255];
}
}else{
memset(ans,0,1024);
i=r-l;
for (uint *u=bl[ib2].a+l;i;++u,--i) ++ans[(*u>>s)&255];
}
}
void frequency1(uint r,uint *ans,uint i0=0,uint i1=256){
uint i,pos,*p,ib,np,d;
uint **P=ps;
const uint s=SH;
ib=root;
np=d=0;
for (i=hi;1<i;--i){
p=b[ib].b;
for (pos=0;p[pos]<r;++pos) r-=p[pos];
if (pos) P[np++]=b[ib].c+(pos-1)*256;
else P[np]=b[ib].c;
ib=b[ib].a[pos];
}
if (np){
if (p[pos]<r+r){
if (pos) P[np-1]+=256;
else ++np;
d=1;
}
freq1(P,np,ans,i0,i1);
if (d==0){
for (uint *u=bl[ib].a;r;++u,--r) ++ans[(*u>>s)&255];
}else{
i=bl[ib].n-r;
for (uint *u=bl[ib].a+r;i;++u,--i) --ans[(*u>>s)&255];
}
}else{
memset(ans,0,1024);
for (uint *u=bl[ib].a;r;++u,--r) ++ans[(*u>>s)&255];
}
}
uint ranklt(uchar x){
uint i,s=0;
if (1<hi){
uint *p=memi;
for (i=x>>4;i;s+=p[--i]);
p=b[root].c+((b[root].n-1)*256+(x&0xf0));
for (i=x&0x0f;i;s+=p[--i]);
}else{
//uchar *q=bl[root].a;
//for (i=bl[root].n;i;) if (q[--i]<x) ++s;
uint *q=bl[root].a;
for (i=0;i<bl[root].n;++i){
if (((q[i]>>SH)&255)<x) ++s;
}
}
return s;
}
uint rank(uint r,uchar x){
uint i,*p,ib=root;
uint pos=UINT_MAX;
uint s=0;
const uint y=(uint)x<<SH;
const uint m=MS;
for (i=hi;1<i;--i){
p=b[ib].b;
for (pos=0;p[pos]<r;++pos) r-=p[pos];
p=b[ib].c+(pos*256+x);
if (pos) s+=p[-256];
ib=b[ib].a[pos];
}
if (pos!=UINT_MAX && !*p) return s;
if (r+r<=bl[ib].n || pos==UINT_MAX){
for (uint *q=bl[ib].a;r;++q,--r){
if ((*q&m)==y) ++s;
}
}else{
s+=pos? *p-p[-256]:*p;
i=bl[ib].n-r;
for (uint *q=bl[ib].a+r;i;++q,--i){
if ((*q&m)==y) --s;
}
}
return s;
}
uint slct_s3(uint k,uint n_,uchar x,uint *ansp,uint *ansv){
uint i,ib,lk,uk,pos,h,*pb,s,t,r,*p,k_,*w=W;
const uint n_0=n_;
const uint u=(uint)x<<SH;
const uint m=MS;
h=hi;
w[0]=ib=root;
w[1]=lk=0;
w[2]=uk=UINT_MAX;
s=pos=0;
for (uint pop=1;n_;pop=1){
if (1<h){
if (k<uk){
p=b[ib].c+(pos*256+x);
pb=b[ib].b;
for (r=b[ib].n;pos=uk) break;
}
}
}
}
if (pop){
++h;
w-=5;
ib=w[0];lk=w[1];uk=w[2];s=w[3];pos=w[4];
}
}
return n_0-n_;
}
uint c_include(uint *pc,uint pos,uint xs,uint xr){
if (pos){
for (uint *p=pc-256;xs<xr;++xs){
if (p[xs]<pc[xs]) return 1;
}
}else{
for (;xs<xr;++xs){
if (pc[xs]) return 1;
}
}
return 0;
}
uint rangereport4(const uint ql,const uint qr,const uint xs,const uint xr,uint *ansp,uint *ansv,const uint x_0,const uint x_1,uint cmp){
if (ql>=qr || xs>=xr) return 0;
uint i,ib,pos,h,*pb,*pc,r,*p,nl,nr,*w=W;
const uint h_=h=hi;
const uint *ansp_=ansp;
w[0]=ib=root;
pos=nl=0;
for (uint pop=1;1;pop=1){
if (1<h){
pb=b[ib].b;
pc=b[ib].c+pos*256;
for (r=b[ib].n;pos=qr || ql>=(nl+pb[pos]) || !c_include(pc,pos,xs,xr));pc+=256,++pos) nl+=pb[pos];
if (pos<r){
w[1]=nl+pb[pos]; // =nr
w[2]=pos+1;
w+=3;
w[0]=ib=b[ib].a[pos];
pos=0;
pop=0;
--h;
}
}else{
i=(ql<=nl)? 0:ql-nl;
nr=nl+bl[ib].n;
r=(nr<qr)? bl[ib].n:qr-nl;
p=bl[ib].a;
if (cmp==1){
for (;i<r;++i){
if (x_0<=p[i]){
*ansv=p[i];++ansv;
*ansp=nl+i;++ansp;
}
}
}else if (cmp==2){
for (;i<r;++i){
if (p[i]<x_1){
*ansv=p[i];++ansv;
*ansp=nl+i;++ansp;
}
}
}else{
for (;i<r;++i){
if (x_0<=p[i] && p[i]<x_1){
*ansv=p[i];++ansv;
*ansp=nl+i;++ansp;
}
}
}
}
if (pop){
if (h==h_) break;
w-=3;
ib=w[0];nl=w[1];pos=w[2];
++h;
}
}
return ansp-ansp_;
}
void sequence(uint l,uint r,uint *ans){
uint *p,pos,ib=root;
uint t,u,k=l;
for (uint h=hi;1<h;--h){
p=b[ib].b;
for (pos=0;k>=p[pos];++pos) k-=p[pos];
ib=b[ib].a[pos];
}
u=r-l;
t=(u<=bl[ib].n-k)? u:bl[ib].n-k;
memcpy(ans,bl[ib].a+k,t*szx);
for (u-=t;u;u-=t){
ib=bl[ib].pleaf;
ans+=t;
t=(u<=bl[ib].n)? u:bl[ib].n;
memcpy(ans,bl[ib].a,t*szx);
}
}
void getcsum(uint *ans){
if (1<hi){
uint i,s,*p=b[root].c+(b[root].n-1)*256;
for (i=s=0;i<256;++i){
ans[i]=s;
s+=p[i];
}
}else{
c_count_leaf(root,bl[root].n,ans,1);
memmove(ans+1,ans,255*4);
ans[0]=0;
for (uint i=2;i<256;++i) ans[i]+=ans[i-1];
}
}
void leaf_sequence(uint ib,uint k,uint n_,uint *ans){
uint t=bl[ib].n-k;
t=(n_<=t)? n_:t;
memcpy(ans,bl[ib].a+k,t*szx);
for (n_-=t;n_;n_-=t){
ib=bl[ib].pleaf;
ans+=t;
t=(n_<=bl[ib].n)? n_:bl[ib].n;
memcpy(ans,bl[ib].a,t*szx);
}
}
void seqs3(uint *ls,uint *ns,uint na,uint *ans){
uint ib,d,dnext,pos,h,*pb,k,t,*w=W;
const uint h_=h=hi;
w[0]=ib=root;
w[1]=d=0;
w[2]=dnext=UINT_MAX;
pos=0;
for (uint pop=1;na;pop=1){
if (1<h){
if (*ls<dnext){
pb=b[ib].b;
for (k=*ls;d+pb[pos]<=k;++pos) d+=pb[pos];
w[1]=d;
w[3]=pos;
w+=4;
w[0]=ib=b[ib].a[pos];
w[2]=dnext=d+pb[pos];
pos=0;
pop=0;
--h;
}
}else{
k=*ls-d;
t=*ns;
leaf_sequence(ib,k,t,ans);
ans+=t;
++ls;++ns;
--na;
}
if (pop && h<h_){
++h;
w-=4;
ib=w[0];d=w[1];dnext=w[2];pos=w[3];
}
}
}
uint rep_ls(uint l,uint r,const uint x_0,const uint x_1,uint *ans){
uint *p,pos,ib=root;
uint s,t,u,k=l;
for (uint h=hi;1<h;--h){
p=b[ib].b;
for (pos=0;k>=p[pos];++pos) k-=p[pos];
ib=b[ib].a[pos];
}
u=r-l;
for (s=0;u;ib=bl[ib].pleaf){
t=(u<=bl[ib].n-k)? u:bl[ib].n-k;
p=bl[ib].a+k;k=0;
for (u-=t;t;--t,++p){
if (x_0<=*p && *p<x_1) ans[s++]=*p;
}
}
return s;
}
uint rep_ls(uint l,uint r,const uint x_0,const uint x_1,uint *ansp,uint *ansv){
uint *p,*q,pos,ib=root;
uint s,t,u,k=l;
for (uint h=hi;1<h;--h){
p=b[ib].b;
for (pos=0;k>=p[pos];++pos) k-=p[pos];
ib=b[ib].a[pos];
}
u=r-l;
for (s=0;u;ib=bl[ib].pleaf){
t=(u<=bl[ib].n-k)? u:bl[ib].n-k;
p=bl[ib].a+k;k=0;
u-=t;
for (q=p+t;p<q;++p,++l){
if (x_0<=*p && *p<x_1){
ansv[s]=*p;
ansp[s]=l;
++s;
}
}
}
return s;
}
uint repme_ls(uint l,uint r,const uint x,uint *ans){
uint *p,pos,ib=root;
uint s,t,u,k=l;
for (uint h=hi;1<h;--h){
p=b[ib].b;
for (pos=0;k>=p[pos];++pos) k-=p[pos];
ib=b[ib].a[pos];
}
u=r-l;
for (s=0;u;ib=bl[ib].pleaf){
t=(u<=bl[ib].n-k)? u:bl[ib].n-k;
p=bl[ib].a+k;k=0;
for (u-=t;t;--t,++p){
if (x<=*p) ans[s++]=*p;
}
}
return s;
}
uint repme_ls(uint l,uint r,const uint x,uint *ansp,uint *ansv){
uint *p,*q,pos,ib=root;
uint s,t,u,k=l;
for (uint h=hi;1<h;--h){
p=b[ib].b;
for (pos=0;k>=p[pos];++pos) k-=p[pos];
ib=b[ib].a[pos];
}
u=r-l;
for (s=0;u;ib=bl[ib].pleaf){
t=(u<=bl[ib].n-k)? u:bl[ib].n-k;
p=bl[ib].a+k;k=0;
u-=t;
for (q=p+t;p<q;++p,++l){
if (x<=*p){
ansv[s]=*p;
ansp[s]=l;
++s;
}
}
}
return s;
}
uint replt_ls(uint l,uint r,const uint x,uint *ans){
uint *p,pos,ib=root;
uint s,t,u,k=l;
for (uint h=hi;1<h;--h){
p=b[ib].b;
for (pos=0;k>=p[pos];++pos) k-=p[pos];
ib=b[ib].a[pos];
}
u=r-l;
for (s=0;u;ib=bl[ib].pleaf){
t=(u<=bl[ib].n-k)? u:bl[ib].n-k;
p=bl[ib].a+k;k=0;
for (u-=t;t;--t,++p){
if (*p<x) ans[s++]=*p;
}
}
return s;
}
uint replt_ls(uint l,uint r,const uint x,uint *ansp,uint *ansv){
uint *p,*q,pos,ib=root;
uint s,t,u,k=l;
for (uint h=hi;1<h;--h){
p=b[ib].b;
for (pos=0;k>=p[pos];++pos) k-=p[pos];
ib=b[ib].a[pos];
}
u=r-l;
for (s=0;u;ib=bl[ib].pleaf){
t=(u<=bl[ib].n-k)? u:bl[ib].n-k;
p=bl[ib].a+k;k=0;
u-=t;
for (q=p+t;p<q;++p,++l){
if (*p<x){
ansv[s]=*p;
ansp[s]=l;
++s;
}
}
}
return s;
}
uint rank_ls(uint l,uint r,const uint x){
uint *p,pos,ib=root;
uint s,t,u,k=l;
for (uint h=hi;1<h;--h){
p=b[ib].b;
for (pos=0;k>=p[pos];++pos) k-=p[pos];
ib=b[ib].a[pos];
}
u=r-l;
for (s=0;u;ib=bl[ib].pleaf){
t=(u<=bl[ib].n-k)? u:bl[ib].n-k;
p=bl[ib].a+k;k=0;
for (u-=t;t;--t,++p){
if (*p==x) ++s;
}
}
return s;
}
};
class wm_report_minkmaxk{
private:
uint ntree,SH,W[256*3*3+1024*2];
Btree256 *B;
node *b;
leaf_node *bl;
uint repme(uint it,uint l,uint r,uint x,uint sh,uint *w0,uint *ans){
uint i,j,l2,r2,t,*w1,*wc,ret=0;
const uint d=(x>>sh)&255;
if (r-l<=2048){
ret=B[it].repme_ls(l,r,x,ans);
}else if (sh){
w1=w0+256;wc=w1+256;
B[it].frequency1(l,w0,d,256);
B[it].frequency1(r,w1,d,256);
B[it].getcsum(wc);
i=wc[d];
l2=i+w0[d];
r2=i+w1[d];
j=0;
for (i=d+1;i<256;++i){
if (w0[i]<w1[i]){
w1[j]=w1[i]-w0[i];
w0[j]=w0[i]+wc[i];
ret+=w1[j];
++j;
}
}
t=(l2<r2)? repme(it-1,l2,r2,x,sh-8,wc,ans):0;
if (j) B[it-1].seqs3(w0,w1,j,ans+t);
ret+=t;
}else{
B[it].frequency(l,r,w0);
const uint u=x&0xffffff00;
for (i=d;i<256;++i){
for (t=w0[i];t;--t) ans[ret++]=u|i;
}
}
return ret;
}
uint replt(uint it,uint l,uint r,uint x,uint sh,uint *w0,uint *ans){
uint i,j,l2,r2,t,*w1,*wc,ret=0;
const uint d=(x>>sh)&255;
if (r-l<=2048){
ret=B[it].replt_ls(l,r,x,ans);
}else if (sh){
w1=w0+256;wc=w1+256;
B[it].frequency1(l,w0,0,d+1);
B[it].frequency1(r,w1,0,d+1);
B[it].getcsum(wc);
i=wc[d];
l2=i+w0[d];
r2=i+w1[d];
j=0;
for (i=0;i<d;++i){
if (w0[i]<w1[i]){
w1[j]=w1[i]-w0[i];
w0[j]=w0[i]+wc[i];
ret+=w1[j];
++j;
}
}
if (j) B[it-1].seqs3(w0,w1,j,ans);
if (l2<r2) ret+=replt(it-1,l2,r2,x,sh-8,w0,ans+ret);
}else{
B[it].frequency(l,r,w0);
const uint u=x&0xffffff00;
for (i=0;i<d;++i){
for (t=w0[i];t;--t) ans[ret++]=u|i;
}
}
return ret;
}
uint rngrep2(uint it,uint l,uint r,uint x_0,uint x_1,uint sh,uint *w0,uint *ans){
uint i,j,l2,r2,l3,r3,t,*w1,*wc,ret=0;
const uint xs=(x_0>>sh)&255;
const uint xt=(x_1>>sh)&255;
if (r-l<=2048){
ret=B[it].rep_ls(l,r,x_0,x_1,ans);
}else if (sh==0){
B[it].frequency(l,r,w0);
const uint u=x_0&0xffffff00;
for (i=xs;i<xt;++i){
for (t=w0[i];t;--t) ans[ret++]=u|i;
}
}else if (xs==xt){
l2=B[it].rank(l,xs);
r2=B[it].rank(r,xs);
if (l2<r2){
i=B[it].ranklt(xs);
ret=rngrep2(it-1,i+l2,i+r2,x_0,x_1,sh-8,w0,ans);
}
}else{
w1=w0+256;wc=w1+256;
B[it].frequency1(l,w0,xs,xt+1);
B[it].frequency1(r,w1,xs,xt+1);
B[it].getcsum(wc);
i=wc[xs];
l2=i+w0[xs];
r2=i+w1[xs];
i=wc[xt];
l3=i+w0[xt];
r3=i+w1[xt];
j=0;
for (i=xs+1;i<xt;++i){
if (w0[i]<w1[i]){
w1[j]=w1[i]-w0[i];
w0[j]=w0[i]+wc[i];
ret+=w1[j];
++j;
}
}
t=(l2<r2)? repme(it-1,l2,r2,x_0,sh-8,wc,ans):0;
if (j) B[it-1].seqs3(w0,w1,j,ans+t);
ret+=t;
if (l3<r3) ret+=replt(it-1,l3,r3,x_1,sh-8,w0,ans+ret);
}
return ret;
}
void rngmnk2(uint it,uint l,uint r,uint k,const uint u,uint sh,uint *ans,uint *w0){
uint i,j,t,*w1,*wc,k_=k;
if (r-l<=1024){
B[it].sequence(l,r,w0);
qs_k(w0,k-1,r-l);
memcpy(ans,w0,k*4);
}else if (sh){
w1=w0+256;wc=w1+256;
B[it].frequency1(l,w0);
B[it].frequency1(r,w1);
B[it].getcsum(wc);
for (i=j=0;k;++i){
if (w0[i]<w1[i]){
w1[j]=w1[i]-w0[i];
w0[j]=w0[i]+wc[i];
if (k<w1[j]) break;
k-=w1[j];
++j;
}
}
if (j) B[it-1].seqs3(w0,w1,j,ans);
if (k) rngmnk2(it-1,w0[j],w0[j]+w1[j],k,u|(i<<sh),sh-8,ans+(k_-k),w0);
}else{
B[it].frequency(l,r,w0);
for (i=j=0;k;++i){
for (t=w0[i];t && k;--t,--k) ans[j++]=u|i;
}
}
}
void select_nj_s(uint it,uint n_,uint x,uint sh,uint *ansp){
uint i,t;
uchar y;
for (;it<ntree;++it,sh+=8){
y=(x>>sh)&255;
t=B[it].ranklt(y);
if (t) for (i=0;i<n_;++i) ansp[i]-=t;
B[it].slct_s3(ansp,n_,y);
}
}
void rngmnk_pos2(uint it,uint l,uint r,uint k,const uint u,uint sh,uint *w0,uint *ansp,uint *ansv){
uint i,t,*w1,*ansp_=ansp;
if (r-l<=1024){
t=r-l;
w1=w0+t;
B[it].sequence(l,r,w0);
for (i=0;i<t;++i) w1[i]=l+i;
qs2_i_k(w0,w1,k-1,t);
qs2(w1,w0,k,w1+t);
memcpy(ansv,w0,k*4);
memcpy(ansp,w1,k*4);
select_nj_s(it+1,k,u,sh+8,ansp);
}else{
w1=w0+256;
B[it].frequency1(l,w0);
B[it].frequency1(r,w1);
for (i=0;k;++i){
if (w0[i]<w1[i]){
t=w1[i]-w0[i];
if (k<t) break;
k-=t;
ansp+=t;
}
}
if (ansp!=ansp_){
t=ansp-ansp_;
B[it].rangereport4(l,r,0,i,ansp_,ansv,0,u|(i<<sh),2);
ansv+=t;
select_nj_s(it+1,t,u,sh+8,ansp_);
}
if (k){
if (sh){
t=B[it].ranklt(i);
uint l2=t+w0[i];
uint r2=t+w1[i];
rngmnk_pos2(it-1,l2,r2,k,u|(i<<sh),sh-8,w0,ansp,ansv);
}else{
B[it].slct_s3(w0[i],k,i,ansp,ansv);
select_nj_s(it+1,k,u,sh+8,ansp);
}
}
}
}
void rngmxk2(uint it,uint l,uint r,uint k,const uint u,uint sh,uint *ans,uint *w0){
uint i,j,t,*w1,*wc;
if (r-l<=1024){
B[it].sequence(l,r,w0);
qs_k(w0,(r-l)-k,r-l);
memcpy(ans,w0+((r-l)-k),k*4);
}else if (sh){
w1=w0+256;wc=w1+256;
B[it].frequency1(l,w0);
B[it].frequency1(r,w1);
B[it].getcsum(wc);
for (i=j=255;k;--i){
if (w0[i]<w1[i]){
w1[j]=w1[i]-w0[i];
w0[j]=w0[i]+wc[i];
if (k<w1[j]) break;
k-=w1[j];
--j;
}
}
if (j!=255) B[it-1].seqs3(w0+(j+1),w1+(j+1),255-j,ans+k);
if (k) rngmxk2(it-1,w0[j],w0[j]+w1[j],k,u|(i<<sh),sh-8,ans,w0);
}else{
B[it].frequency(l,r,w0);
for (i=255;k;--i){
for (t=w0[i];t && k;--t) ans[--k]=u|i;
}
}
}
void rngmxk_pos2(uint it,uint l,uint r,uint k,const uint u,uint sh,uint *w0,uint *ansp,uint *ansv){
uint i,t,*w1,*ansp_=ansp;
if (r-l<=1024){
t=r-l;
w1=w0+t;
B[it].sequence(l,r,w0);
for (i=0;i<t;++i) w1[i]=l+i;
qs2_i_k(w0,w1,t-k,t);
w0+=t-k;w1+=t-k;
qs2(w1,w0,k,w1+t);
memcpy(ansv,w0,k*4);
memcpy(ansp,w1,k*4);
select_nj_s(it+1,k,u,sh+8,ansp);
}else{
w1=w0+256;
B[it].frequency1(l,w0);
B[it].frequency1(r,w1);
for (i=255;k;--i){
if (w0[i]<w1[i]){
t=w1[i]-w0[i];
if (k<t) break;
k-=t;
ansp+=t;
}
}
if (ansp!=ansp_){
t=ansp-ansp_;
B[it].rangereport4(l,r,i+1,256,ansp_,ansv,u|((i+1)<<sh),0,1);
ansv+=t;
select_nj_s(it+1,t,u,sh+8,ansp_);
}
if (k){
if (sh){
t=B[it].ranklt(i);
uint l2=t+w0[i];
uint r2=t+w1[i];
rngmxk_pos2(it-1,l2,r2,k,u|(i<<sh),sh-8,w0,ansp,ansv);
}else{
B[it].slct_s3(w0[i],k,i,ansp,ansv);
select_nj_s(it+1,k,u,sh+8,ansp);
}
}
}
}
uint repme_pos(uint it,uint l,uint r,uint x,uint sh,uint *ansp,uint *ansv){
uint i,l2,r2,t,ret=0;
const uint d=(x>>sh)&255;
if (r-l<=1024){
ret=B[it].repme_ls(l,r,x,ansp,ansv);
if (ret) select_nj_s(it+1,ret,x,sh+8,ansp);
}else if (sh){
l2=B[it].rank(l,d);
r2=B[it].rank(r,d);
if (l2<r2){
i=B[it].ranklt(d);
ret=repme_pos(it-1,i+l2,i+r2,x,sh-8,ansp,ansv);
ansp+=ret;ansv+=ret;
}
t=B[it].rangereport4(l,r,d+1,256,ansp,ansv,((x>>sh)+1)<<sh,0,1);
if (t) select_nj_s(it+1,t,x,sh+8,ansp);
ret+=t;
}else{
t=B[it].rangereport4(l,r,d,256,ansp,ansv,x,0,1);
if (t) select_nj_s(it+1,t,x,sh+8,ansp);
ret+=t;
}
return ret;
}
uint replt_pos(uint it,uint l,uint r,uint x,uint sh,uint *ansp,uint *ansv){
uint i,l2,r2,ret=0;
const uint d=(x>>sh)&255;
if (r-l<=1024){
ret=B[it].replt_ls(l,r,x,ansp,ansv);
if (ret) select_nj_s(it+1,ret,x,sh+8,ansp);
}else{
ret=B[it].rangereport4(l,r,0,d,ansp,ansv,0,(x>>sh)<<sh,2);
if (ret) select_nj_s(it+1,ret,x,sh+8,ansp);
if (sh){
l2=B[it].rank(l,d);
r2=B[it].rank(r,d);
if (l2<r2){
i=B[it].ranklt(d);
ret+=replt_pos(it-1,i+l2,i+r2,x,sh-8,ansp+ret,ansv+ret);
}
}
}
return ret;
}
uint rngrep_pos2(uint it,uint l,uint r,uint x_0,uint x_1,uint sh,uint *ansp,uint *ansv){
uint i,l2,r2,l3,r3,t,ret=0;
const uint xs=(x_0>>sh)&255;
const uint xt=(x_1>>sh)&255;
if (r-l<=1024){
ret=B[it].rep_ls(l,r,x_0,x_1,ansp,ansv);
if (ret) select_nj_s(it+1,ret,x_0,sh+8,ansp);
}else if (sh==0){
ret=B[it].rangereport4(l,r,xs,xt,ansp,ansv,x_0,x_1,3);
if (ret) select_nj_s(it+1,ret,x_0,sh+8,ansp);
}else if (xs==xt){
l2=B[it].rank(l,xs);
r2=B[it].rank(r,xs);
if (l2<r2){
i=B[it].ranklt(xs);
ret=rngrep_pos2(it-1,i+l2,i+r2,x_0,x_1,sh-8,ansp,ansv);
}
}else{
l2=B[it].rank(l,xs);
r2=B[it].rank(r,xs);
if (l2<r2){
i=B[it].ranklt(xs);
ret=repme_pos(it-1,i+l2,i+r2,x_0,sh-8,ansp,ansv);
ansp+=ret;ansv+=ret;
}
if (xs+1<xt){
t=B[it].rangereport4(l,r,xs+1,xt,ansp,ansv,((x_0>>sh)+1)<<sh,(x_1>>sh)<<sh,3);
if (t) select_nj_s(it+1,t,x_0,sh+8,ansp);
ansp+=t;ansv+=t;ret+=t;
}
l3=B[it].rank(l,xt);
r3=B[it].rank(r,xt);
if (l3<r3){
i=B[it].ranklt(xt);
ret+=replt_pos(it-1,i+l3,i+r3,x_1,sh-8,ansp,ansv);
}
}
return ret;
}
public:
// n:最大入力件数
// m:最大入力値
wm_report_minkmaxk(uint n,uint m){
uint i,j,ni,nl;
double c=0.4;
ntree=0;
for (i=m;i;i>>=8) ++ntree;
SH=(ntree-1)*8;
nl=(double)n/(c*binfo.leafsize);
ni=((double)nl-1)/(c*binfo.M-1);
++nl,++ni;
B=new Btree256[ntree];
b=new node[ni*ntree];
bl=new leaf_node[nl*ntree];
for (i=0,j=ntree-1;i<ntree;++i,--j){
B[j].init_mem(b+i*ni,bl+i*nl,nl,j*8);
}
memset(W,0,256*4);
}
~wm_report_minkmaxk(){
delete [] B;delete [] b;delete [] bl;
}
// 初期化時に数列の最後尾にxを追加する
void init(uint x){
B[ntree-1].init(x);
++W[x>>SH];
}
// init後にこれを実行すると初期化完了
void init_end(){
uint i,j,k,n_,x,ix,*wc,*w1,s=SH;
wc=W;w1=W+256;ix=0;
for (i=n_=0;i<256;++i) n_+=wc[i];
for (i=ntree-1;0<i;--i,s-=8){
for (j=1;j<256;++j) wc[j]+=wc[j-1];
memset(w1,0,256*4);
for (j=n_;j--;){
x=B[i].init_access_x(j);
k=--wc[(x>>s)&255];
B[i-1].init2(k,x);
++w1[(x>>(s-8))&255];
}
memcpy(wc,w1,256*4);
}
for (i=ntree;i--;) B[i].init_end();
}
// i番目の要素を返す
uint access(uint i){
return B[ntree-1].access(i);
}
// i番目にxを追加
void insert(uint i,uint x){
uint j,k,s=SH;
uchar y;
for (j=ntree;j--;s-=8){
y=(x>>s)&255;
k=B[j].insert_rank(i,x,j);
if (j) i=B[j].ranklt(y)+k;
}
}
// i番目の要素を削除
uint remove(uint i){
uint j,k,x,s=SH;
uint y=256;
for (j=ntree;j--;s-=8){
k=B[j].remove_rank(i,j);
if (y==256) x=B[j].removed_x();
y=(x>>s)&255;
if (j) i=B[j].ranklt(y)+k;
}
return x;
}
// [l,r)に含まれるxの個数
uint rank(uint l,uint r,uint x){
uint i,j,y,s=SH;
if (l>=r) return 0;
for (i=ntree;i-- && l<r;s-=8){
if (255<r-l){
y=(x>>s)&255;
j=i? B[i].ranklt(y):0;
l=j+B[i].rank(l,y);
r=j+B[i].rank(r,y);
}else{
return B[i].rank_ls(l,r,x);
}
}
return r-l;
}
// [l,r)に含まれるx以上y未満の要素をans配列に返す
// rangereportは解の個数を返す
uint rangereport(uint l,uint r,uint x,uint y,uint *ans){
if (l>=r || x>=y) return 0;
return rngrep2(ntree-1,l,r,x,y,SH,W,ans);
}
// [l,r)に含まれる要素のうち小さい方からk個をans配列に返す
void rangemink(uint l,uint r,uint k,uint *ans){
if (l>=r || k>r-l) return;
rngmnk2(ntree-1,l,r,k,0,SH,ans,W);
}
// [l,r)に含まれる要素のうち小さい方からk個をans_val配列に返す
// ans_pos[i]=ans_val[i]の位置
void rangemink_pos(uint l,uint r,uint k,uint *ans_pos,uint *ans_val){
if (l>=r || k>r-l || !k) return;
rngmnk_pos2(ntree-1,l,r,k,0,SH,W,ans_pos,ans_val);
}
// [l,r)に含まれる要素のうち大きい方からk個をans配列に返す
void rangemaxk(uint l,uint r,uint k,uint *ans){
if (l>=r || k>r-l || !k) return;
rngmxk2(ntree-1,l,r,k,0,SH,ans,W);
}
// [l,r)に含まれる要素のうち大きい方からk個をans_val配列に返す
// ans_pos[i]=ans_val[i]の位置
void rangemaxk_pos(uint l,uint r,uint k,uint *ans_pos,uint *ans_val){
if (l>=r || k>r-l || !k) return;
rngmxk_pos2(ntree-1,l,r,k,0,SH,W,ans_pos,ans_val);
}
// [l,r)に含まれるx以上y未満の要素をans_val配列に返す
// ans_pos[i]=ans_val[i]の位置
// rangereport_posは解の個数を返す
uint rangereport_pos(uint l,uint r,uint x,uint y,uint *ans_pos,uint *ans_val){
if (l>=r || x>=y) return 0;
return rngrep_pos2(ntree-1,l,r,x,y,SH,ans_pos,ans_val);
}
};
int main(void){
const uint N=1000000; // 最大入力件数
const uint M=UINT_MAX; // 最大入力値
const uint n=100000; // クエリの回数(大)
const uint n_small=10000; // クエリの回数(小)
const uint k=100; // rangeminkのk
uint i,j,t,l,r,x,y,ret;
uint *anspos=new uint[N];
uint *ansval=new uint[N];
wm_report_minkmaxk wm(N,M);
// N要素で初期化
std::cout<<"init(input size="<<N<<")"<<std::endl;
for (i=0;i<N;++i){
x= (double)rand() / (RAND_MAX + 1) * (M);
wm.init(x);
}
wm.init_end();
std::cout<<std::endl;std::cout<<std::endl;std::cout<<std::endl;
// n要素削除
std::cout<<"remove *"<<n<<std::endl;
for (i=0;i<n;++i){
j= (double)rand() / (RAND_MAX + 1) * (N-i);
wm.remove(j);
}
std::cout<<std::endl;std::cout<<std::endl;std::cout<<std::endl;
// n要素追加
std::cout<<"insert *"<<n<<std::endl;
for (i=n;0<i;--i){
j= (double)rand() / (RAND_MAX + 1) * (N-i);
x= (double)rand() / (RAND_MAX + 1) * (M);
wm.insert(j,x);
}
std::cout<<std::endl;std::cout<<std::endl;std::cout<<std::endl;
// rangemink n回
std::cout<<"rangemink *"<<n<<std::endl;
for (i=0;i<n;++i){
do{
l= (double)rand() / (RAND_MAX + 1) * (N);
r= (double)rand() / (RAND_MAX + 1) * (N);
if (l>r) t=l,l=r,r=t;
}while (k>r-l);
wm.rangemink(l,r,k,ansval);
// wm.rangemaxk(l,r,k,ansval);
}
// 最後のクエリの結果を表示
std::cout<<"rangemink(l,r,k)"<<std::endl;
std::cout<<"l="<<l<<",r="<<r<<",k="<<k<<std::endl;
std::cout<<std::endl;
for (i=0;i<k;++i){
std::cout<<ansval[i]<<",";
}
std::cout<<std::endl;std::cout<<std::endl;std::cout<<std::endl;std::cout<<std::endl;
// rangereport n回
// l,r,xを乱数で決めてそれに応じて解がk個程になるようにyを決める
// 最後に解の個数の平均を表示する
std::cout<<"rangereport *"<<n<<std::endl;
const double Mk=(double)M*(double)k;
unsigned long long avg=0ULL;
for (i=0;i<n;++i){
do{
l= (double)rand() / (RAND_MAX + 1) * (N);
r= (double)rand() / (RAND_MAX + 1) * (N);
if (l>r) t=l,l=r,r=t;
}while (k>r-l);
do{
x= (double)rand() / (RAND_MAX + 1) * (M);
y=x+Mk/(double)(r-l);
}while (x>y || y>M);
ret=wm.rangereport(l,r,x,y,ansval);
avg+=(unsigned long long)ret;
}
// 最後のクエリの結果を表示
std::cout<<"rangereport(l,r,x,y)"<<std::endl;
std::cout<<"l="<<l<<",r="<<r<<std::endl;
std::cout<<"x="<<x<<",y="<<y<<std::endl;
std::cout<<"output size="<<ret<<std::endl;
std::cout<<std::endl;
for (i=0;i<ret;++i){
std::cout<<ansval[i]<<",";
}
std::cout<<std::endl;std::cout<<std::endl;
std::cout<<"average output size="<<(double)avg/(double)n<<std::endl;
std::cout<<std::endl;std::cout<<std::endl;std::cout<<std::endl;
// 位置の取得は遅いのでクエリを1万回にする
// rangemink_pos n_small回
std::cout<<"rangemink_pos *"<<n_small<<std::endl;
for (i=0;i<n_small;++i){
do{
l= (double)rand() / (RAND_MAX + 1) * (N);
r= (double)rand() / (RAND_MAX + 1) * (N);
if (l>r) t=l,l=r,r=t;
}while (k>r-l);
wm.rangemink_pos(l,r,k,anspos,ansval);
// wm.rangemaxk_pos(l,r,k,anspos,ansval);
}
// 最後のクエリの結果を表示
// val(i)=access(pos(i)) でなくてはいけない
std::cout<<"rangemink_pos(l,r,k,pos,val)"<<std::endl;
std::cout<<"l="<<l<<",r="<<r<<",k="<<k<<std::endl;
std::cout<<std::endl;
std::cout<<"i,pos(i),val(i),access(pos(i))"<<std::endl;
for (i=0;i<k;++i){
t=wm.access(anspos[i]);
std::cout<<i<<","<<anspos[i]<<","<<ansval[i]<<","<<t<<std::endl;
}
std::cout<<std::endl;std::cout<<std::endl;std::cout<<std::endl;
// rangereport_pos n_small回
std::cout<<"rangereport_pos *"<<n_small<<std::endl;
avg=0ULL;
for (i=0;i<n_small;++i){
do{
l= (double)rand() / (RAND_MAX + 1) * (N);
r= (double)rand() / (RAND_MAX + 1) * (N);
if (l>r) t=l,l=r,r=t;
}while (k>r-l);
do{
x= (double)rand() / (RAND_MAX + 1) * (M);
y=x+Mk/(double)(r-l);
}while (x>y || y>M);
ret=wm.rangereport_pos(l,r,x,y,anspos,ansval);
avg+=(unsigned long long)ret;
}
// 最後のクエリの結果を表示
// val(i)=access(pos(i)) でなくてはいけない
std::cout<<"rangereport_pos(l,r,x,y,pos,val)"<<std::endl;
std::cout<<"l="<<l<<",r="<<r<<std::endl;
std::cout<<"x="<<x<<",y="<<y<<std::endl;
std::cout<<"output size="<<ret<<std::endl;
std::cout<<std::endl;
std::cout<<"i,pos(i),val(i),access(pos(i))"<<std::endl;
for (i=0;i<ret;++i){
t=wm.access(anspos[i]);
std::cout<<i<<","<<anspos[i]<<","<<ansval[i]<<","<<t<<std::endl;
}
std::cout<<std::endl;
std::cout<<"average output size="<<(double)avg/(double)n_small<<std::endl;
std::cout<<std::endl;std::cout<<std::endl;
delete [] anspos;
delete [] ansval;
return 0;
}

