zoukankan      html  css  js  c++  java
  • BZOJ2741:[FOTILE模拟赛]L

    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

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

    题解:

    把元素数组aa替换为前缀异或和数组qz,则询问变成了指定区间内最大的两个元素异或和。

    假如某个元素x已经确定,那么我们只要在区间中找到一个数y,使x xor y最大。

    这可以用字典树在O(log)的复杂度内实现。因为是指定的一个区间,所以要采用可持久化字典树。

    为了减少复杂度,采取分块的做法。

    将n分为√n块,对于每块的第一个元素i,用a[i,j]表示i到j的区间中的最大连续异或和。

    转移方式:a[i,j]:=max(a[i,j-1],qz[j]在[i,j-1]的字典树中的最大异或和)。

    注意不要忘了以[i,j]异或和作为答案的情况(即qz[i-1]xor qz[j])。

    预处理好a数组后,开始处理询问[l,r]。

    找到第一个比l大的分块首元素i(i=k*√n+1),分情况讨论。

    若r≥i,则答案为max(a[i,r],qz[l≤j≤i-1]在[j+1,r]的字典树中的最大异或和);

    若r<i,则答案为max(qz[l≤j≤r]在[l,j-1]的字典树中的最大异或和),注意考虑以[l,j]异或和作为答案的情况(即qz[l-1]xor qz[j])。

    代码:

     1 uses math;
     2 var
     3   t:array[0..600000,0..1,0..1]of longint;
     4   a:array[0..120,0..12001]of longint;
     5   qz,aa:array[0..12001]of longint;
     6   r:array[0..12001]of longint;
     7   b:array[0..34]of longint;
     8   i,ii,j,k,n,m,block,mm,cnt,x,y,ans:longint;
     9   l,ll,rr:int64;
    10 procedure cl(y,yy,z:longint);
    11 var i:longint;
    12 begin
    13   if z=-1 then exit;
    14   i:=x and(1 shl z);
    15   if i>0 then
    16   begin
    17     inc(cnt); t[yy,0]:=t[y,0];
    18     t[yy,1,1]:=cnt; t[yy,1,0]:=t[y,1,0]+1;
    19     cl(t[y,1,1],t[yy,1,1],z-1); exit;
    20   end;
    21   inc(cnt); t[yy,1]:=t[y,1];
    22   t[yy,i,1]:=cnt; t[yy,i,0]:=t[y,i,0]+1;
    23   cl(t[y,i,1],t[yy,i,1],z-1);
    24 end;
    25 function qq(y,yy,z:longint):longint;
    26 var i:longint;
    27 begin
    28   if z=-1 then exit(0);
    29   i:=x and(1 shl z);
    30   if i>0 then
    31   begin
    32     if t[yy,0,0]-t[y,0,0]>0 then
    33     exit(b[z]+qq(t[y,0,1],t[yy,0,1],z-1));
    34     exit(qq(t[y,1,1],t[yy,1,1],z-1));
    35   end;
    36   if t[yy,1,0]-t[y,1,0]>0 then
    37   exit(b[z]+qq(t[y,1,1],t[yy,1,1],z-1));
    38   exit(qq(t[y,0,1],t[yy,0,1],z-1));
    39 end;
    40 begin
    41   b[0]:=1;
    42   for i:=1 to 30 do b[i]:=b[i-1]*2;
    43   readln(n,m);
    44   for i:=1 to n do
    45   begin
    46     read(aa[i]); qz[i]:=aa[i] xor qz[i-1]; x:=qz[i];
    47     inc(cnt); r[i]:=cnt; cl(r[i-1],cnt,30);
    48   end;
    49   block:=trunc(sqrt(n)*1.5)+1;
    50   block:=min(n,block);
    51   i:=1;
    52   while i<=n do
    53   begin
    54     inc(mm);
    55     a[mm,i]:=aa[i];
    56     for j:=i+1 to n do
    57     begin
    58       x:=qz[j]; a[mm,j]:=max(a[mm,j-1],x xor qz[i-1]);
    59       a[mm,j]:=max(a[mm,j],qq(r[i-1],r[j-1],30));
    60     end;
    61     i:=i+block;
    62   end;
    63   for i:=1 to m do
    64   begin
    65     readln(ll,rr);
    66     l:=max((ll+ans)mod n+1,(rr+ans)mod n+1);
    67     ll:=min((ll+ans)mod n+1,(rr+ans)mod n+1);
    68     k:=l; j:=ll; l:=0;
    69     while block*l+1<=j do inc(l);
    70     if block*l+1<=k then
    71     begin
    72       ans:=a[l+1,k]; l:=block*l;
    73       for ii:=j to l do
    74       begin
    75         x:=qz[ii-1];
    76         ans:=max(ans,qq(r[ii-1],r[k],30));
    77       end;
    78     end else
    79     begin
    80       ans:=aa[j];
    81       for ii:=j+1 to k do
    82       begin
    83         x:=qz[ii]; ans:=max(ans,x xor qz[j-1]);
    84         ans:=max(ans,qq(r[j-1],r[ii-1],30));
    85       end;
    86     end;
    87     writeln(ans);
    88   end;
    89 end.
    View Code
  • 相关阅读:
    ORACLE SEQUENCE 介绍
    cocos2d 游戏开发:Cocos2d v3 &quot;hello world&quot;+显示飞船
    无线网络覆盖
    解决xShell4某些情况下按删除键会输出^H的问题
    Android开发经验之—intent传递大数据
    简单的REST的框架实现
    ListView 使用方法(Asp.Net)
    POJ2528 Mayor&#39;s posters 【线段树】+【成段更新】+【离散化】
    C#反射Assembly 具体说明
    HDU 4432 Sum of divisors (进制模拟)
  • 原文地址:https://www.cnblogs.com/GhostReach/p/6273214.html
Copyright © 2011-2022 走看看