1. 程式人生 > 其它 >[整理]莫隊二次離線

[整理]莫隊二次離線

莫隊二次離線用於處理移動區間端點時複雜度過大的問題。
以擴充套件區間 \([l,r]\)\([l,r+1]\) 為例,設多出的貢獻為 \(f(r+1,[l,r])\),這個貢獻必須是可以差分成 \(f(r+1,[1,r])-f(r+1,[1,l-1])\) 形式的。
到這裡你當然可以把它們直接全部離線下來算貢獻,但是你的空間複雜度會比較爆炸。讓我們再來仔細觀察這個東西,減號前面的部分可以簡簡單單預處理,後面的東西貢獻的區間都是固定的,我們再把它離線一次。
和普通莫隊一樣需要分情況討論,這裡以從 \([l,r]\) 移動到 \([l,R]\)(其中 \(R\) 為查詢區間端點)為例,我們計算出減號前的貢獻,再在字首 \(l-1\)

位置放一個查詢 \([r+1,R]\) 表示計算這個區間的貢獻。

if(R>r)q1[l-1].pub({r+1,R,i});//把詢問離線到相應的位置
while(R>r)q[i].ans+=pre[++r];//順便計算減號前貢獻

對於其他幾種情況是同理的,需要注意符號。
然後我們發現,在處理左端點移動時,會出現形如 \(f(l,[1,l])\) 的東西,我們沒有處理過它,於是可以假裝它是我們處理過的 \(f(l,[1,l-1])\)。而只有 \(k=0\) 時相等的元素會有影響,所以特判一下即可。
模板題核心程式碼(預處理那裡運用了異或的一些性質):

const int N=200010;
int n,m,pp,a[N],bel[N],len,ans[N];
struct Query {
  int l,r,idx,ans;
}q[N];
bool operator < (Query A,Query B){
  return bel[A.l]==bel[B.l]?A.r<B.r:bel[A.l]<bel[B.l];
}
struct Query1 {
  int l,r,idx,sgn;
};
vector<Query1> q1[N];
vector<int> buc;
int b[N],pre[N];
signed main(){
  Read(n),Read(m),Read(pp),len=sqrt(n);
  for(rg int i=1;i<=n;i++)Read(a[i]);
  for(rg int i=1;i<=m;i++)Read(q[i].l),Read(q[i].r),q[i].idx=i;
  for(rg int i=1;i<=n;i++)bel[i]=(i-1)/len+1;
  sort(q+1,q+1+m);
  for(rg int i=0;i<=16384;i++){
    if(__builtin_popcount(i)==pp)buc.pub(i);
  }
  for(rg int i=1;i<=n;i++){
    pre[i]=b[a[i]];
    for(rg auto j:buc)b[a[i]^j]++;
  }
  for(rg int i=1,l=1,r=0;i<=m;i++){
    int L=q[i].l,R=q[i].r;
    if(L<l)q1[r].pub({L,l-1,i,1});
    while(L<l)q[i].ans-=pre[--l];
    if(L>l)q1[r].pub({l,L-1,i,-1});
    while(L>l)q[i].ans+=pre[l++];
    if(R>r)q1[l-1].pub({r+1,R,i,-1});
    while(R>r)q[i].ans+=pre[++r];
    if(R<r)q1[l-1].pub({R+1,r,i,1});
    while(R<r)q[i].ans-=pre[r--];
  }
  memset(b,0,sizeof(b));
  for(rg int i=1;i<=n;i++){
    for(rg auto j:buc)b[a[i]^j]++;
    for(rg auto j:q1[i]){
      for(rg int k=j.l;k<=j.r;k++){
        q[j.idx].ans+=j.sgn*(b[a[k]]-(k<=i&&!pp));
      }
    }
  }
  for(rg int i=1;i<=m;i++)q[i].ans+=q[i-1].ans;
  for(rg int i=1;i<=m;i++)ans[q[i].idx]=q[i].ans;
  for(rg int i=1;i<=m;i++)cout<<ans[i]<<endl;
  KafuuChino HotoKokoa
}