zoukankan      html  css  js  c++  java
  • bzoj2741【FOTILE模拟赛】L(可持久化trie树+分块)

    区间上的异或问题,不难想到用可持久化线段树解决

    求l到r的最大异或和,暴力自然是枚举左右端点,但显然时间不允许

    用分块的方法处理

    枚举右端点,处理出每个右端点到每个快左端点的区间最大异或和

    询问时暴力枚举不在块内的点作为左端点即可

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 int n,m,tot,num,ans;
     7 int rt[12005];
     8 int vl[12005];
     9 int tr[400005][2];
    10 int siz[400005];
    11 int f[155][12005];
    12 void insert(int fr,int tim,int s){
    13     int now=rt[tim]=++tot;
    14     for(int i=30;i>=0;i--){
    15         tr[now][!((s>>i)&1)]=tr[fr][!((s>>i)&1)];
    16         tr[now][(s>>i)&1]=++tot;
    17         now=tr[now][(s>>i)&1];
    18         fr=tr[fr][(s>>i)&1];
    19         siz[now]=siz[fr]+1;
    20     }
    21 }
    22 int query(int s,int fr,int now){
    23     int ret=0;
    24     for(int i=30;i>=0;i--){
    25         if(siz[tr[now][!((s>>i)&1)]]>siz[tr[fr][!((s>>i)&1)]]){
    26             ret|=(1<<i);
    27             now=tr[now][!((s>>i)&1)];
    28             fr=tr[fr][!((s>>i)&1)];
    29         }else{
    30             now=tr[now][(s>>i)&1];
    31             fr=tr[fr][(s>>i)&1];
    32         }
    33     }
    34     return ret;
    35 }
    36 void getprt(){
    37     for(int i=1;i<=(n/num)+1;i++){
    38         for(int j=(i-1)*num+1;j<=n;j++){
    39             int l=(i-1)*num-1;int r=rt[j-1];
    40             l=(l<0)?0:rt[l];
    41             f[i][j]=max(f[i][j-1],query(vl[j],l,r));
    42         }
    43     }
    44 }
    45 int main(){
    46     scanf("%d%d",&n,&m);
    47     num=sqrt(n+1)+1;
    48     insert(0,0,0);
    49     for(int i=1;i<=n;i++){
    50         scanf("%d",&vl[i]);
    51         vl[i]^=vl[i-1];
    52         insert(rt[i-1],i,vl[i]);
    53     }
    54     getprt();
    55     for(int i=1;i<=m;i++){
    56         int l,r;
    57         scanf("%d%d",&l,&r);
    58         l=((long long)l+ans)%n+1;r=((long long)r+ans)%n+1;
    59         if(l>r)swap(l,r);
    60         int p=l/num+2;
    61         ans=f[p][r];
    62         for(int j=l;j<=min((p-1)*num,r);j++){
    63             ans=max(ans,query(vl[j-1],rt[l-1],rt[r]));
    64         }
    65         printf("%d
    ",ans);
    66     }
    67     return 0;
    68 }
  • 相关阅读:
    LINQ分组排序后获取每组第一条记录
    String 中的Trim
    C# Switch优雅写法
    C# 输入指定日期获取当前年的第一天 、当前年的最后天、某月的第一天 、某月的最后一天
    快捷方式 ABP——切换MySQL数据库
    新建立git分支,之后将分支合并到master上
    C# Contains()、 == 和Equals() 比较
    使用TimeSpan 日期与时间拼接
    ActiveReports报表行号
    iOS基础(八)——最新更新方法,每天只提示一次
  • 原文地址:https://www.cnblogs.com/lnxcj/p/10031486.html
Copyright © 2011-2022 走看看