• Codeforces 617E XOR and Favorite Number


    Discription

    Bob has a favorite number k and ai of length n. Now he asks you to answer m queries. Each query is given by a pair li and ri and asks you to count the number of pairs of integers i and j, such that l ≤ i ≤ j ≤ r and the xor of the numbers ai, ai + 1, ..., ajis equal to k.

    Input

    The first line of the input contains integers nm and k (1 ≤ n, m ≤ 100 000, 0 ≤ k ≤ 1 000 000) — the length of the array, the number of queries and Bob's favorite number respectively.

    The second line contains n integers ai (0 ≤ ai ≤ 1 000 000) — Bob's array.

    Then m lines follow. The i-th line contains integers li and ri (1 ≤ li ≤ ri ≤ n) — the parameters of the i-th query.

    Output

    Print m lines, answer the queries in the order they appear in the input.

    Example

    Input
    6 2 3
    1 2 1 1 0 3
    1 6
    3 5
    Output
    7
    0
    Input
    5 3 1
    1 1 1 1 1
    1 5
    2 4
    1 3
    Output
    9
    4
    4

    Note

    In the first sample the suitable pairs of i and j for the first query are: (1, 2), (1, 4), (1, 5), (2, 3), (3, 6), (5, 6), (6, 6). Not a single of these pairs is suitable for the second query.

    In the second sample xor equals 1 for all subarrays of an odd length.

    一个比较显然的做法是找出所有点对之后上主席树,然后我就RE了hhh,这说明点对还是有点多的,,,

    先放一个我RE的代码,,,改完了再贴正解

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<set>
    #include<queue>
    #include<vector>
    #define ll long long
    #define pb push_back
    #define maxn 100005
    using namespace std;
    //g[i]是前缀异或和==i的位置链表 
    vector<int> g[maxn*10];
    //point[i]以i为右端点的满足条件的对的左端点集合 
    vector<int> point[maxn];
    int n,k,now,pre,sz;
    int pos,m,le,ri;
    
    struct node{
        int s,lc,rc;
    }nil[maxn*177];
    int rot[maxn],cnt=0;
    
    int update(int u,int l,int r){
        int ret=++cnt;
        nil[ret]=nil[u];
        nil[ret].s++;
        
        if(l==r) return ret;
        
        int mid=l+r>>1;
        if(le<=mid) nil[ret].lc=update(nil[ret].lc,l,mid);
        else nil[ret].rc=update(nil[ret].rc,mid+1,r);
        
        return ret;
    }
    
    int query(int u,int l,int r){
        if(l>=le&&r<=ri) return nil[u].s;
        int an=0,mid=l+r>>1;
        if(le<=mid) an=query(nil[u].lc,l,mid);
        if(ri>mid) an+=query(nil[u].rc,mid+1,r);
        
        return an;
    }
    
    inline void prework(){
        nil->s=0;
        
        for(int i=1;i<=n;i++){
            rot[i]=rot[i-1];
            for(int j=point[i].size()-1;j>=0;j--){
                le=point[i][j];
                rot[i]=update(rot[i],1,n);
            }
        }
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        pre=0,g[0].pb(0);
        for(int i=1;i<=n;i++){
            scanf("%d",&now);
            pre^=now,now=k^pre;
            
            sz=g[now].size();
            for(int j=0;j<sz;j++){
                pos=g[now][j];
                point[i].pb(pos+1);
            }
            
            g[pre].pb(i);
        }
        
        prework();
        
        while(m--){
            scanf("%d%d",&le,&ri);
            printf("%d
    ",query(rot[ri],1,n));
        }
        
        return 0;
    }

     第二遍莫队。。。然而又RE了。。。。

    (估计是点对太多不能直接存hhhhh)

    等我再改改

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<set>
    #include<queue>
    #include<vector>
    #define ll long long
    #define pb push_back
    #define maxn 100005
    using namespace std;
    //g[i]是前缀异或和==i的位置链表 
    vector<int> g[maxn*10];
    //point[i]以i为右端点的满足条件的对的左端点集合 
    vector<int> point[maxn];
    vector<int> rig[maxn];
    int n,k,now,pre,sz;
    int pos,m,le,ri,tot;
    
    /*
    struct node{
        int s,lc,rc;
    }nil[maxn*177];
    int rot[maxn],cnt=0;
    
    int update(int u,int l,int r){
        int ret=++cnt;
        nil[ret]=nil[u];
        nil[ret].s++;
        
        if(l==r) return ret;
        
        int mid=l+r>>1;
        if(le<=mid) nil[ret].lc=update(nil[ret].lc,l,mid);
        else nil[ret].rc=update(nil[ret].rc,mid+1,r);
        
        return ret;
    }
    
    int query(int u,int l,int r){
        if(l>=le&&r<=ri) return nil[u].s;
        int an=0,mid=l+r>>1;
        if(le<=mid) an=query(nil[u].lc,l,mid);
        if(ri>mid) an+=query(nil[u].rc,mid+1,r);
        
        return an;
    }
    
    inline void prework(){
        nil->s=0;
        
        for(int i=1;i<=n;i++){
            rot[i]=rot[i-1];
            for(int j=point[i].size()-1;j>=0;j--){
                le=point[i][j];
                rot[i]=update(rot[i],1,n);
            }
        }
    }
    */
    
    struct node{
        int l,r,bl,num;
        bool operator <(const node& u)const{
            return bl==u.bl?((bl&1)?r<u.r:r>u.r):bl<u.bl;
        }
    }q[maxn];
    int ans[maxn];
    
    inline void adl(int x){
        tot+=upper_bound(rig[x].begin(),rig[x].end(),ri)-rig[x].begin();
    }
    
    inline void del(int x){
        tot-=upper_bound(rig[x].begin(),rig[x].end(),ri)-rig[x].begin();
    }
    
    inline void adr(int x){
        tot+=point[x].size()-(lower_bound(point[x].begin(),point[x].end(),le)-point[x].begin());
    }
    
    inline void der(int x){
        tot-=point[x].size()-(lower_bound(point[x].begin(),point[x].end(),le)-point[x].begin());    
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        pre=0,g[0].pb(0);
        for(int i=1;i<=n;i++){
            scanf("%d",&now);
            pre^=now,now=k^pre;
            
            sz=g[now].size();
            for(int j=0;j<sz;j++){
                pos=g[now][j];
                //枚举顺序保证了两个链表的元素都是升序的 
                point[i].pb(pos+1);
                rig[pos+1].pb(i);
            }
            
            g[pre].pb(i);
        }
        
        sz=sqrt(n);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].bl=(q[i].l-1)/sz+1;
            q[i].num=i;
        }
        sort(q+1,q+m+1);
        
        le=1,ri=0;
        for(int i=1;i<=m;i++){
            while(le<q[i].l) del(le),le++;
            while(le>q[i].l) le--,adl(le);
            while(ri<q[i].r) ri++,adr(ri);
            while(ri>q[i].r) der(ri),ri--;
            
            ans[q[i].num]=tot;
        }
        
        for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
        return 0;
    }

     虽然现在A了但是首先声明一下之前让我RE的可能不是炸数组而是xor出的数>=1000000,,,,,

    现在写了一个正确的莫队。。。。

    其实不用计点对,现算也来得及(二分)

    Accepted

    #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> #include<set> #include<queue> #include<vector> #define ll long long #define pb push_back #define maxn 100005 using namespace std; //g[i]是前缀异或和==i的位置链表 vector<int> g[maxn*33]; int n,k,now,pre,sz,a[maxn]; int pos,m,le,ri; ll tot=0; struct node{ int l,r,bl,num; bool operator <(const node& u)const{ return bl==u.bl?((bl&1)?r<u.r:r>u.r):bl<u.bl; } }q[maxn]; ll ans[maxn]; inline void adl(int x){ int to=k^a[x-1]; if(!g[to].size()) return; tot+=(ll)(upper_bound(g[to].begin(),g[to].end(),ri)-lower_bound(g[to].begin(),g[to].end(),x)); } inline void del(int x){ //因为对于本题插入和删除带来的数值影响相同, //所以不用反着操作 int to=k^a[x-1]; if(!g[to].size()) return; tot-=(ll)(upper_bound(g[to].begin(),g[to].end(),ri)-lower_bound(g[to].begin(),g[to].end(),x)); } inline void adr(int x){ int to=k^a[x]; if(!g[to].size()) return; tot+=(ll)(lower_bound(g[to].begin(),g[to].end(),x)-lower_bound(g[to].begin(),g[to].end(),le-1)); } inline void der(int x){ int to=k^a[x]; if(!g[to].size()) return; tot-=(ll)(lower_bound(g[to].begin(),g[to].end(),x)-lower_bound(g[to].begin(),g[to].end(),le-1)); } int main(){ scanf("%d%d%d",&n,&m,&k); g[0].pb(0); for(int i=1;i<=n;i++){ scanf("%d",a+i); a[i]^=a[i-1]; g[a[i]].pb(i); } sz=sqrt(n); for(int i=1;i<=m;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].bl=(q[i].l-1)/sz+1; q[i].num=i; } sort(q+1,q+m+1); le=1,ri=0; for(int i=1;i<=m;i++){ while(le<q[i].l) del(le),le++; while(le>q[i].l) le--,adl(le); while(ri<q[i].r) ri++,adr(ri); while(ri>q[i].r) der(ri),ri--; ans[q[i].num]=tot; } for(int i=1;i<=m;i++) printf("%lld ",ans[i]); return 0; }
  • 相关阅读:
    英语语法基础知识总结名词
    英语语法基础知识代词
    idea破解第二部
    Linux(centos)系统下安装fastdfs安装部署步骤
    死磕Synchronized底层实现概论偏向锁轻量级锁重量级锁
    深入理解Mysql事务隔离级别与锁机制
    事务的传播机制
    ICCV2021 | TokenstoToken ViT:在ImageNet上从零训练Vision Transformer
    计算机视觉CV技术指南文章汇总
    资源分享 | PyTea:不用运行代码,静态分析pytorch模型的错误
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8371381.html
Copyright © 2020-2023  润新知