#pragma once
#include<cassert>
#include<vector>classFullyIndexableDictionary{intn,block;// 64個事に区切ったブロックの個数std::vector<unsignedlonglong>bit;std::vector<unsignedint>sum;// ブロック毎の累積和boolprepared;public:FullyIndexableDictionary(){}FullyIndexableDictionary(intn):n(n),block((n+63)>>6),bit(block,0),sum(block+1,0),prepared(false){}boolis_prepared(){returnprepared;}voidset(intk){bit[k>>6]|=1ull<<(k&63);sum[(k>>6)+1]++;}voidbuild(){assert(!prepared);prepared=true;for(inti=0;i<block;i++)sum[i+1]+=sum[i];}booloperator[](intk)const{returnbool((bit[k>>6]>>(k&63))&1);}// [0,j) の合計intrank(intj,boolf=1){assert(prepared);inta=sum[j>>6]+__builtin_popcountll(bit[j>>6]&((1ull<<(j&63))-1));return(f?a:j-a);}// 0-indexed で k 番目の f の場所intselect(intk,boolf=1){assert(prepared);if(k<0orrank(n,f)<=k)return-1;intl=0,r=n;while(r-l>1){intm=(l+r)>>1;(rank(m,f)>=k+1?r:l)=m;}returnr-1;}// l以上で k 番目の f の場所intselect(intk,boolf,intl){returnselect(rank(l,f)+k,f);}};
#line 2 "library/datastructure/FullyIndexableDictionary.hpp"
#include<cassert>
#include<vector>classFullyIndexableDictionary{intn,block;// 64個事に区切ったブロックの個数std::vector<unsignedlonglong>bit;std::vector<unsignedint>sum;// ブロック毎の累積和boolprepared;public:FullyIndexableDictionary(){}FullyIndexableDictionary(intn):n(n),block((n+63)>>6),bit(block,0),sum(block+1,0),prepared(false){}boolis_prepared(){returnprepared;}voidset(intk){bit[k>>6]|=1ull<<(k&63);sum[(k>>6)+1]++;}voidbuild(){assert(!prepared);prepared=true;for(inti=0;i<block;i++)sum[i+1]+=sum[i];}booloperator[](intk)const{returnbool((bit[k>>6]>>(k&63))&1);}// [0,j) の合計intrank(intj,boolf=1){assert(prepared);inta=sum[j>>6]+__builtin_popcountll(bit[j>>6]&((1ull<<(j&63))-1));return(f?a:j-a);}// 0-indexed で k 番目の f の場所intselect(intk,boolf=1){assert(prepared);if(k<0orrank(n,f)<=k)return-1;intl=0,r=n;while(r-l>1){intm=(l+r)>>1;(rank(m,f)>=k+1?r:l)=m;}returnr-1;}// l以上で k 番目の f の場所intselect(intk,boolf,intl){returnselect(rank(l,f)+k,f);}};