1 solutions

  • 0
    @ 2024-1-5 17:21:33

    可持久化0/1tire

    题意:可持久化数据结构,求从l,r区间选一个位置开始,一直异或到最后然后与x进行异或,求最大为多少。

    分析:

    1. [l,r] 作为起点,N作为终点,那么 r+1~n 的值一定会与x进行异或,是一个定值。提前处理。
    2. 要使异或值最大,那肯定是越前的位数就要相反。即建立树的时候从高位开始建。
    3. 在1和2的基础上,要使得更快更有效的方法,怎么实现??? 前缀和思想 !! 建树的时候,建的就是前缀异或和的树, 求答案的时候,就用[ l , r ]区间的值去和 x^s[n]看怎么走异或值最大 如果用s[y]代表前缀异或和的话。那么最大值=s[n]^x^ s ( l , r ) = ( a[1]^a[2]……a[n] ) ^ x ^ ( a[1] ^ a[2] ^ …… ^ a[ (l,r) ] ),求由于s[n]^x为定值,我们只需要从r位置开始求前缀异或和后尽量与s[n]^相反的值就可以了 直接上代码

    insert(int x,int y,int i)

    插入前缀异或和 x是当前插入的位置编号,y是上一个节点的编号,i是插入的是第几个数(用于判断是否超出范围)

    void insert( int x,int y,int i ) 
    {  vesion[x]=i; 
       for(int k=len;k>=0;k--) 
       {  int c=s[i]>>k&1; 
          ch[ x ][ !c ]=ch[ y ][ !c ];  //离他本身最近的那个节点但值相反的位置在哪
          ch[ x ][ c ]=++idx; //为自己建节点。
          x=ch[x][c],y=ch[y][c]; 
         vesion[x]=i;  //这个位置是第i个
        } 
    }
    

    插入的时候插入前缀异或和,并记录前缀相同的位置

    quire( int x,int l,int v )

    查询函数,要求最左端不超过l,并且该位置与v异或值相反的最大值。

    int quire( int x,int l,int v )
    {
      int ans=0;  //记录答案
      for(int k=len;k>=0;k--)  //从高位开始异或
      {
        int c=(v>>k)&1;   //获取这个位置的二进制值
        if( vesion[ch[x][!c]]>=l )  //如果往反方向走没有走出l的位置
          x=ch[x][!c],ans+=1<<k;  //走过去,并且答案增加
        else x=ch[x][c];  //反之走不过去,答案不更新
      }
      return ans;
    }
    

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=6e5+12,len=23;
    int ch[N*25][2],s[N],vesion[N*25],idx,root[N];
    void insert( int x,int y,int i )
    {
      vesion[x]=i;
      for(int k=len;k>=0;k--)
      {
        int c=s[i]>>k&1;
        ch[ x ][ !c ]=ch[ y ][ !c ];
        ch[ x ][ c ]=++idx;
        x=ch[x][c],y=ch[y][c];
        vesion[x]=i;
      }
    }
    int quire( int x,int l,int v )
    {
      int ans=0;
      for(int k=len;k>=0;k--)
      {
        int c=(v>>k)&1;
        if( vesion[ch[x][!c]]>=l )
          x=ch[x][!c],ans+=1<<k;
        else x=ch[x][c];
      }
      return ans;
    }
    int n,m;
    int main(){
      char p;
      int x,l,r;  
      vesion[0]=-1;
      root[0]=++idx;
      insert(root[0],0,0);
      cin>>n>>m;
      for(int i=1;i<=n;i++)
      {
        cin>>x;
        s[i]=s[i-1]^x;
        root[i]=++idx;
        insert( root[i],root[i-1],i );
      }
      while(m--)
      {
        cin>>p;
        if( p=='A' )
        {
          cin>>x;
          n++;
          s[n]=s[n-1]^x;
          root[n]=++idx;
          insert( root[n],root[n-1],n );
        }
        else
        {
          cin>>l>>r>>x;
          cout<<quire( root[r-1],l-1,s[n]^x )<<endl;
        }
    
      }
    
    
    }
    
    • 1

    Information

    ID
    12654
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    10
    Tags
    (None)
    # Submissions
    1
    Accepted
    1
    Uploaded By