P4462 [CQOI2018] 异或序列

莫队典题了算是。
先转化一下题意。
\(a\) 序列做一个异或前缀和。
然后就转化为了查询 \(l-1,r\) 区间内前缀和互相异或能得到 \(k\) 的对数。
直接莫队做完了。

点击查看代码
#include<bits/stdc++.h>
#define p_b push_back
#define e_b emplace_back
#define ll long long
#define pii pair<int,int>
#define fir first
#define sec second
#define il inline
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define int ll
using namespace std;
const int N=1e5+5,inf=1e9;
int n,m,k,a[N];
int bsz,B[N];
struct Qry{
    int l,r,id;
}q[N];
bool cmp(Qry a,Qry b){return B[a.l]^B[b.l]?B[a.l]<=B[b.l]:(B[a.l]&1?a.r<b.r:a.r>b.r);}
int cnt[2*N],now,ans[N];
void del(int p){cnt[a[p]]--;now-=cnt[a[p]^k];}
void add(int p){now+=cnt[a[p]^k];cnt[a[p]]++;}
signed main(){
    ios;cin>>n>>m>>k;bsz=n/sqrt(m);if(!bsz)bsz=1;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)a[i]^=a[i-1],B[i]=(i-1)/bsz+1;
    for(int i=1;i<=m;i++)cin>>q[i].l>>q[i].r,q[i].id=i;
    sort(q+1,q+m+1,cmp);
    int l=0,r=0;cnt[0]=1;
    for(int i=1;i<=m;i++){
        int ql=q[i].l-1,qr=q[i].r;
        while(l>ql)add(--l);
        while(l<ql)del(l++);
        while(r<qr)add(++r);
        while(r>qr)del(r--);
        //cout<<ql<<' '<<qr<<' '<<now<<'\n';
        ans[q[i].id]=now;
    }
    for(int i=1;i<=m;i++)cout<<ans[i]<<'\n';
}
posted @ 2025-10-10 15:19  zhuoheng  阅读(7)  评论(0)    收藏  举报