This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub tko919/library
#include "DataStructure/rangelis.hpp"
#pragma once #include "DataStructure/wavelet.hpp" struct RangeLIS{ WaveletMatrix<int> wm; int N; RangeLIS(vector<int> p){ N=1; while(N<int(p.size()))N<<=1; rep(i,p.size(),N)p.push_back(i); auto init=seaweed(p); wm=WaveletMatrix<int>(init); } int query(int L,int R){ if(L>=R)return 0; return R-L-wm.freq(0,R,L,N); } private: vector<int> seaweed(const vector<int>& p){ int n=p.size(); if(n==1)return {inf}; vector<int> lo,hi,lpos,hpos; rep(i,0,n){ if(p[i]<n/2){ lo.push_back(p[i]); lpos.push_back(i); } else{ hi.push_back(p[i]-n/2); hpos.push_back(i); } } auto x=seaweed(lo),y=seaweed(hi); vector<int> s(n),t(n); iota(ALL(s),0); iota(ALL(t),0); int xi=0,yi=0; rep(i,0,n){ if(p[i]<n/2){ if(x[xi]==inf)s[i]=inf; else s[i]=lpos[x[xi]]; xi++; } else{ if(y[yi]==inf)t[i]=inf; else t[i]=hpos[y[yi]]; yi++; } } vector<int> a(n,inf),b(n); vector<int> revs(n,inf); rep(i,0,n)if(s[i]!=inf)revs[s[i]]=i; int pos=n-1; vector<int> tos(n,inf),tot(n,inf); for(int i=n-1;i>=0;i--)if(revs[i]!=inf){ a[revs[i]]=pos; tos[pos--]=i; } rep(i,0,n)if(a[i]==inf)a[i]=pos--; pos=0; vector<int> used(n); rep(i,0,n)if(t[i]!=inf){ b[pos]=t[i]; tot[pos++]=i; used[t[i]]=1; } rep(i,0,n)if(!used[i]){ b[pos++]=i; } auto c=squaredot(a,b); vector<int> res(n,inf); rep(i,0,n)if(tot[i]!=inf and tos[c[i]]!=inf){ res[tot[i]]=tos[c[i]]; } return res; } vector<int> squaredot(const vector<int>& a,const vector<int>& b){ int n=a.size(); if(n==1)return {0}; vector<int> alo,ahi,blo,bhi; vector<int> inva(n); rep(i,0,n)inva[a[i]]=i; int aloi=0,ahii=0; vector<int> azip(n),alov,ahiv; rep(i,0,n){ if(inva[i]<n/2){ azip[inva[i]]=aloi++; alov.push_back(i); } else{ azip[inva[i]]=ahii++; ahiv.push_back(i); } if(b[i]<n/2)blo.push_back(b[i]); else bhi.push_back(b[i]-n/2); } rep(i,0,n){ if(i<n/2)alo.push_back(azip[i]); else ahi.push_back(azip[i]); } auto sublo=squaredot(alo,blo); auto subhi=squaredot(ahi,bhi); vector<int> clo(n,inf),chi(n,inf),res(n,inf); int subloi=0,subhii=0; rep(i,0,n){ if(b[i]<n/2)clo[i]=alov[sublo[subloi++]]; else chi[i]=ahiv[subhi[subhii++]]; } vector<int> invclo(n,inf),invchi(n,inf); rep(i,0,n){ if(clo[i]!=inf)invclo[clo[i]]=i; if(chi[i]!=inf)invchi[chi[i]]=i; } int cloi=n,cloj=-1,chii=n,chij=-1; int ldelta=0,hdelta=0; for(;;){ if(cloi<0 and chij>=n)break; if(ldelta>0){ cloj++; if(cloj<n and chi[cloj]!=inf and chi[cloj]<cloi)ldelta--; if(cloj<n and clo[cloj]!=inf and clo[cloj]>=cloi)ldelta--; } else{ cloi--; if(cloi>=0 and invchi[cloi]!=inf and invchi[cloi]<=cloj)ldelta++; if(cloi>=0 and invclo[cloi]!=inf and invclo[cloi]>cloj)ldelta++; } if(0<=cloj and cloj<n and clo[cloj]!=inf and clo[cloj]<=cloi)res[cloj]=clo[cloj]; if(hdelta>=0){ chij++; if(chij<n and chi[chij]!=inf and chi[chij]<chii)hdelta--; if(chij<n and clo[chij]!=inf and clo[chij]>=chii)hdelta--; } else{ chii--; if(chii>=0 and invchi[chii]!=inf and invchi[chii]<=chij)hdelta++; if(chii>=0 and invclo[chii]!=inf and invclo[chii]>chij)hdelta++; } if(0<=chij and chij<n and chi[chij]!=inf and chi[chij]>=chii)res[chij]=chi[chij]; if(cloi==chii and cloj==chij)res[cloj]=cloi; } return res; } }; /** * @brief Range LIS Query */
#line 2 "DataStructure/wavelet.hpp" template<typename T>struct WaveletMatrix{ struct BitVector{ vector<unsigned long long> buf; vector<int> rui; BitVector(const vector<char>& a={}){ int n=a.size(); buf.assign((n+63)>>6,0); rui.assign(buf.size()+1,0); rep(i,0,n)if(a[i]){ buf[i>>6]|=1ull<<(i&63); rui[(i>>6)+1]++; } rep(i,0,buf.size())rui[i+1]+=rui[i]; } int rank(int k,bool f=1){ int ret=rui[k>>6]+__builtin_popcountll(buf[k>>6]&((1ull<<(k&63))-1)); if(!f)return k-ret; else return ret; } }; int N,lg; vector<int> mid; vector<BitVector> buf; WaveletMatrix(){} WaveletMatrix(vector<T> a):N(a.size()),lg(0){ T mx=0; for(auto& x:a)chmax(mx,x); while((T(1)<<lg)<=mx)lg++; mid.resize(lg); buf.resize(lg); for(int d=lg-1;d>=0;d--){ vector<char> add; vector nxt(2,vector<T>()); for(auto& x:a){ add.push_back(x>>d&1); nxt[x>>d&1].push_back(x); } mid[d]=(int)nxt[0].size(); buf[d]=BitVector(add); swap(a,nxt[0]); a.insert(a.end(),ALL(nxt[1])); } } int rank(int L,int R,T x){ if((T(1)<<lg)<=x)return 0; for(int d=lg-1;d>=0;d--){ bool f=(x>>d&1); L=buf[d].rank(L,f)+(f?mid[d]:0); R=buf[d].rank(R,f)+(f?mid[d]:0); } return R-L; } T quantile(int L,int R,int k){ T ret=0; for(int d=lg-1;d>=0;d--){ int l0=buf[d].rank(L,0),r0=buf[d].rank(R,0); if(k<r0-l0)L=l0,R=r0; else{ k-=r0-l0; ret|=T(1)<<d; L+=mid[d]-l0,R+=mid[d]-r0; } } return ret; } int freq(int L,int R,T x){ if((T(1)<<lg)<=x)return R-L; int ret=0; for(int d=lg-1;d>=0;d--){ bool f=(x>>d&1); if(f)ret+=buf[d].rank(R,0)-buf[d].rank(L,0); L=buf[d].rank(L,f)+(f?mid[d]:0); R=buf[d].rank(R,f)+(f?mid[d]:0); } return ret; } int freq(int L,int R,T a,T b){ return freq(L,R,b)-freq(L,R,a); } T prev(int L,int R,T x){ int cnt=freq(L,R,x); return cnt==R-L?T(-1):quantile(L,R,cnt); } T next(int L,int R,T x){ int cnt=freq(L,R,x); return cnt==0?T(-1):quantile(L,R,cnt-1); } }; /** * @brief Wavelet Matrix * @docs docs/wavelet.md */ #line 3 "DataStructure/rangelis.hpp" struct RangeLIS{ WaveletMatrix<int> wm; int N; RangeLIS(vector<int> p){ N=1; while(N<int(p.size()))N<<=1; rep(i,p.size(),N)p.push_back(i); auto init=seaweed(p); wm=WaveletMatrix<int>(init); } int query(int L,int R){ if(L>=R)return 0; return R-L-wm.freq(0,R,L,N); } private: vector<int> seaweed(const vector<int>& p){ int n=p.size(); if(n==1)return {inf}; vector<int> lo,hi,lpos,hpos; rep(i,0,n){ if(p[i]<n/2){ lo.push_back(p[i]); lpos.push_back(i); } else{ hi.push_back(p[i]-n/2); hpos.push_back(i); } } auto x=seaweed(lo),y=seaweed(hi); vector<int> s(n),t(n); iota(ALL(s),0); iota(ALL(t),0); int xi=0,yi=0; rep(i,0,n){ if(p[i]<n/2){ if(x[xi]==inf)s[i]=inf; else s[i]=lpos[x[xi]]; xi++; } else{ if(y[yi]==inf)t[i]=inf; else t[i]=hpos[y[yi]]; yi++; } } vector<int> a(n,inf),b(n); vector<int> revs(n,inf); rep(i,0,n)if(s[i]!=inf)revs[s[i]]=i; int pos=n-1; vector<int> tos(n,inf),tot(n,inf); for(int i=n-1;i>=0;i--)if(revs[i]!=inf){ a[revs[i]]=pos; tos[pos--]=i; } rep(i,0,n)if(a[i]==inf)a[i]=pos--; pos=0; vector<int> used(n); rep(i,0,n)if(t[i]!=inf){ b[pos]=t[i]; tot[pos++]=i; used[t[i]]=1; } rep(i,0,n)if(!used[i]){ b[pos++]=i; } auto c=squaredot(a,b); vector<int> res(n,inf); rep(i,0,n)if(tot[i]!=inf and tos[c[i]]!=inf){ res[tot[i]]=tos[c[i]]; } return res; } vector<int> squaredot(const vector<int>& a,const vector<int>& b){ int n=a.size(); if(n==1)return {0}; vector<int> alo,ahi,blo,bhi; vector<int> inva(n); rep(i,0,n)inva[a[i]]=i; int aloi=0,ahii=0; vector<int> azip(n),alov,ahiv; rep(i,0,n){ if(inva[i]<n/2){ azip[inva[i]]=aloi++; alov.push_back(i); } else{ azip[inva[i]]=ahii++; ahiv.push_back(i); } if(b[i]<n/2)blo.push_back(b[i]); else bhi.push_back(b[i]-n/2); } rep(i,0,n){ if(i<n/2)alo.push_back(azip[i]); else ahi.push_back(azip[i]); } auto sublo=squaredot(alo,blo); auto subhi=squaredot(ahi,bhi); vector<int> clo(n,inf),chi(n,inf),res(n,inf); int subloi=0,subhii=0; rep(i,0,n){ if(b[i]<n/2)clo[i]=alov[sublo[subloi++]]; else chi[i]=ahiv[subhi[subhii++]]; } vector<int> invclo(n,inf),invchi(n,inf); rep(i,0,n){ if(clo[i]!=inf)invclo[clo[i]]=i; if(chi[i]!=inf)invchi[chi[i]]=i; } int cloi=n,cloj=-1,chii=n,chij=-1; int ldelta=0,hdelta=0; for(;;){ if(cloi<0 and chij>=n)break; if(ldelta>0){ cloj++; if(cloj<n and chi[cloj]!=inf and chi[cloj]<cloi)ldelta--; if(cloj<n and clo[cloj]!=inf and clo[cloj]>=cloi)ldelta--; } else{ cloi--; if(cloi>=0 and invchi[cloi]!=inf and invchi[cloi]<=cloj)ldelta++; if(cloi>=0 and invclo[cloi]!=inf and invclo[cloi]>cloj)ldelta++; } if(0<=cloj and cloj<n and clo[cloj]!=inf and clo[cloj]<=cloi)res[cloj]=clo[cloj]; if(hdelta>=0){ chij++; if(chij<n and chi[chij]!=inf and chi[chij]<chii)hdelta--; if(chij<n and clo[chij]!=inf and clo[chij]>=chii)hdelta--; } else{ chii--; if(chii>=0 and invchi[chii]!=inf and invchi[chii]<=chij)hdelta++; if(chii>=0 and invclo[chii]!=inf and invclo[chii]>chij)hdelta++; } if(0<=chij and chij<n and chi[chij]!=inf and chi[chij]>=chii)res[chij]=chi[chij]; if(cloi==chii and cloj==chij)res[cloj]=cloi; } return res; } }; /** * @brief Range LIS Query */