• 【BZOJ】【2741】【FOTILE模拟赛】L


    可持久化Trie+分块


      神题……Orz zyf & lyd

      首先我们先将整个序列搞个前缀异或和,那么某一段的异或和,就变成了两个数的异或和,所以我们就将询问【某个区间中最大的区间异或和】改变成【某个区间中 max(两个数的异或和)】

      要是我们能将所有[l,r]的答案都预处理出来,那么我们就可以O(1)回答了;然而我们并不能。

      一个常见的折中方案:分块!

      这里先假设我们实现了一个神奇的函数ask(l,r,x),可以帮我们求出[l,r]这个区间中的数,与x最大的异或值。

      我们不预处理所有的左端点,我们只预处理$sqrt{n}$个左端点,与$n$个右端点的答案。

      也就是说:将序列分成$sqrt{n}$块,b[i][j]表示在块 i 的左端到位置 j 这个区间中,选出两个数,其最大的Xor值。

      对于询问[l,r]:设p是$l$后面第一个块的左端点,[p,r]的答案已经在b[p][r]中,[l,p]的答案就是对[l,p]中每个数x执行ask(l,r,x);

      最后:ask(l,r,x)用可持久化Trie实现:具体来说就是,如果能往1走就往1走,如果1这棵子树中所有点都是出现在$l$之前的,那么就往0走。

      可持久化Trie的写法……根据可持久化线段树的写法,yy一下试试?其实差不多= =

     1 /**************************************************************
     2     Problem: 2741
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:6636 ms
     7     Memory:148948 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 2741
    11 #include<cstdio>
    12 #include<cmath>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 #define pb push_back
    21 using namespace std;
    22 typedef long long LL;
    23 inline int getint(){
    24     int r=1,v=0; char ch=getchar();
    25     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
    26     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
    27     return r*v;
    28 }
    29 const int N=150010,M=5e6+10;
    30 /*******************template********************/
    31  
    32 int n,m,q,tot,rt[N],id[M],t[M][2],a[N],b[150][N];
    33  
    34 inline void Ins(int pre,int x,int k){
    35     int now=rt[k]=++tot; id[tot]=k;
    36     D(i,30,0){
    37         int j=(x>>i)&1;
    38         t[now][j^1]=t[pre][j^1];
    39         t[now][j]=++tot; id[tot]=k;
    40         now=tot;
    41         pre=t[pre][j];
    42     }
    43 }
    44 inline int ask(int l,int r,int x){
    45     int ans=0,now=rt[r];
    46     D(i,30,0){
    47         int j=((x>>i)&1)^1;
    48         if (id[t[now][j]]>=l) ans|=1<<i; else j^=1;
    49         now=t[now][j];
    50     }
    51     return ans;
    52 }
    53  
    54 int main(){
    55 #ifndef ONLINE_JUDGE
    56     freopen("2741.in","r",stdin);
    57     freopen("2741.out","w",stdout);
    58 #endif
    59     n=getint(); q=getint();
    60     F(i,1,n) a[i]=a[i-1]^getint();
    61     id[0]=-1;
    62     Ins(rt[0],a[0],0);
    63     F(i,1,n) Ins(rt[i-1],a[i],i);
    64     int len=sqrt(n); m=n/len+(n%len!=0);
    65     rep(i,m) F(j,i*len+1,n)
    66         b[i][j]=max(b[i][j-1],ask(i*len,j-1,a[j]));
    67     int ans=0;
    68     F(i,1,q){
    69         int x=((LL)ans+(LL)getint())%n+1,y=((LL)ans+(LL)getint())%n+1;
    70         if (x>y) swap(x,y);
    71         x--;
    72         int bx=x/len+(x%len!=0);
    73         ans=bx*len < y ? b[bx][y] : 0;
    74         F(j,x,min(bx*len,y))
    75             ans=max(ans,ask(x,y,a[j]));
    76         printf("%d
    ",ans);
    77     }
    78     return 0;
    79 }
    View Code

    2741: 【FOTILE模拟赛】L

    Time Limit: 15 Sec  Memory Limit: 162 MB
    Submit: 1549  Solved: 413
    [Submit][Status][Discuss]

    Description

    FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和。
    即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r。
    为了体现在线操作,对于一个询问(x,y):
    l = min ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).
    r = max ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).
    其中lastans是上次询问的答案,一开始为0。

    Input

    第一行两个整数N和M。
    第二行有N个正整数,其中第i个数为Ai,有多余空格。
    后M行每行两个数x,y表示一对询问。

    Output

     

    共M行,第i行一个正整数表示第i个询问的结果。

    Sample Input

    3 3
    1 4 3
    0 1
    0 1
    4 3


    Sample Output

    5
    7
    7

    HINT



    HINT

    N=12000,M=6000,x,y,Ai在signed longint范围内。

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    微信h5下拉隐藏网页,还有取消页面滑动
    vuejs中使用递归嵌套组件
    运行gitbook init命令报错及问题解决办法
    利用python生成gitbook目录文件
    通过Appium日志,分析其运行原理
    字符串两两更换位置
    Dockerfile启动的程序,内存不断增长问题
    测试流程优化
    APP测试面试题(一)
    关于面试总结13-app测试面试题
  • 原文地址:https://www.cnblogs.com/Tunix/p/4553043.html
Copyright © 2020-2023  润新知