I love counting
O{MlogaMAX(B+N/B)}O\{M\log{a_{\text{MAX}}}(\text{B+N/B})\}O{MlogaMAX(B+N/B)}
md考场写的莫队+Trie一直T
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using pii=pair<int,int>;
using pli=pair<ll,int>;
constexpr ll mod=1e9+7;
//=============================
int rd()
{int res=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res;
}
const int N=100010;
int mp[N];
struct node
{int l,r;int v;
}tree[N*40];int cnt;
int ans[N],Bs;
void insert(int x)
{if(mp[x]!=0) return;mp[x]++;int u=0;for(int i=17;i>=0;i--) {int t=x>>i&1;if(t==0){if(!tree[u].l) tree[u].l=++cnt;u=tree[u].l;}else{if(!tree[u].r) tree[u].r=++cnt;u=tree[u].r;}if(u) tree[u].v++;}
}
void del(int x)
{if(mp[x]==0) return;mp[x]--;int u=0;for(int i=17;i>=0;i--) {int t=x>>i&1;if(t==0)u=tree[u].l;elseu=tree[u].r;if(u) tree[u].v--;}
}
int query(int a,int b)
{int res=0,u=0;for(int i=17;i>=0;i--){int ai=a>>i&1;int bi=b>>i&1;if(bi==1) //b=1{if(ai==0) res+=tree[tree[u].l].v;else res+=tree[tree[u].r].v;if(ai==0) u=tree[u].r;else u=tree[u].l;}else{if(ai==0) u=tree[u].l;else u=tree[u].r;}if(!u) return res;}return res+tree[u].v;
}
int pos[N];
int A[N],n,m;
struct nodeq
{int l,r;int a,b,id;bool operator<(const nodeq&o)const{if(pos[l]==pos[o.l]){if(pos[l]&1)return r<o.r;else return r>o.r;}return pos[l]<pos[o.l];}
}q[N];
int main()
{n=rd();for(int i=1;i<=n;i++) A[i]=rd();m=rd();for(int i=1;i<=m;i++){int l=rd(),r=rd(),a=rd(),b=rd();q[i]={l,r,a,b,i};}Bs=sqrt(n)+1;for(int i=1;i<=n;i++) pos[i]=(i-1)/Bs+1;sort(q+1,q+1+m);for(int i=q[1].l;i<=q[1].r;i++) insert(A[i]);ans[q[1].id]=query(q[1].a,q[1].b);int l=q[1].l,r=q[1].r;for(int i=1;i<=m;i++){while(l<q[i].l) del(A[l++]);while(r>q[i].r) del(A[r--]);while(r<q[i].r) insert(A[++r]);while(l>q[i].l) insert(A[--l]);ans[q[i].id]=query(q[i].a,q[i].b);}for(int i=1;i<=m;i++) printf("%d\n",ans[i]);return 0;
}
Code2
O(MlogNlogaMAX)O(M\log{N}\log{a_{\text{MAX}}})O(MlogNlogaMAX)
和第一场一样,树状数组套Trie
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using pii=pair<int,int>;
using pli=pair<ll,int>;
constexpr ll mod=1e9+7;
//=============================
int rd()
{int res=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res;
}
const int N=100010;
struct node
{int l,r;int v;
}tree[N*400];
int rt[N],cnt;
void insert(int &p,int x)
{if(!p) p=++cnt;int u=p;for(int i=17;i>=0;i--) {int t=x>>i&1;if(t==0){if(!tree[u].l) tree[u].l=++cnt;u=tree[u].l;}else{if(!tree[u].r) tree[u].r=++cnt;u=tree[u].r;}if(u) tree[u].v++;}
}
void del(int u,int x)
{if(!u) return;for(int i=17;i>=0;i--) {int t=x>>i&1;if(t==0)u=tree[u].l;elseu=tree[u].r;if(u) tree[u].v--;}
}
int query(int u,int a,int b)
{int res=0;if(!u) return 0;for(int i=17;i>=0;i--){int ai=a>>i&1;int bi=b>>i&1;if(bi==1) //b=1{if(ai==0) res+=tree[tree[u].l].v;else res+=tree[tree[u].r].v;if(ai==0) u=tree[u].r;else u=tree[u].l;}else{if(ai==0) u=tree[u].l;else u=tree[u].r;}if(!u) return res;}return res+tree[u].v;
}
int A[N],n,m;
int last[N];
int lowbit(int x){return x&-x;}
void Add(int k,int x){for(;k<=n;k+=lowbit(k))insert(rt[k],x);}
void Sub(int k,int x){for(;k<=n;k+=lowbit(k))del(rt[k],x);}int ask(int k,int a,int b)
{int res=0;for(;k;k-=lowbit(k)) res+=query(rt[k],a,b);return res;
}
struct nodeq
{int l,a,b,id;
};
vector<nodeq> q[N];
int ans[N];
int main()
{n=rd();for(int i=1;i<=n;i++) A[i]=rd();m=rd();for(int i=1;i<=m;i++){int l=rd(),r=rd(),a=rd(),b=rd();q[r].push_back({l,a,b,i});}for(int i=1;i<=n;i++){if(last[A[i]]) Sub(last[A[i]],A[i]);Add(i,A[i]);last[A[i]]=i;for(auto t:q[i]) ans[t.id]=ask(i,t.a,t.b)-ask(t.l-1,t.a,t.b);}for(int i=1;i<=m;i++) printf("%d\n",ans[i]);return 0;
}