• hdu5715 XOR 游戏 [2016百度之星复赛D题]


       比赛的时候没仔细想,赛后一想这题其实挺简单的,先求出序列的异或前缀和,然后将异或前缀和建出一颗trie树,然后我们可以二分答案,把问题变成判定性问题,判定是否存在一种方案,使得所有的分组的异或和都大于等于这个二分的答案,然后就可以dp了,用f[i][j]表示到j为止能不能分成i组,f[i][j]=f[i-1][j-k]|f[i-1][j-k+1]...|f[i-1][j-1],这个东西用trie树维护一下就可以了。单组数据复杂度O(nmlogn^2)

      代码

     1 #include<cstdio>
     2 const int N = 1001010;
     3 int num[N],Num[N],trie[N][2],tt,sum[N];
     4 int n,m,l,r,i,k,j,a[N],mid;
     5 int flag[11][N];
     6 void add(int x,int y)
     7 {
     8     int i;
     9     for (i=0;i<=31;i++)
    10     num[i]=x&1,x>>=1;
    11     int t=0;
    12     for (i=31;i>=0;i--)
    13     {
    14         if (trie[t][num[i]]==0) trie[t][num[i]]=++tt;
    15         t=trie[t][num[i]];
    16         sum[t]+=y;
    17     }
    18 }
    19 int find(int x,int y)
    20 {
    21     int i;
    22     for (i=0;i<=31;i++)
    23     {
    24         num[i]=x&1,x>>=1;
    25         Num[i]=y&1,y>>=1;    
    26     }
    27     int t=0;
    28     for (i=31;i>=0;i--)
    29     {
    30         if (Num[i]==1)
    31         {
    32             if (!sum[trie[t][1-num[i]]]) return 0;
    33             else t=trie[t][1-num[i]];
    34         }
    35         else
    36         {
    37             if (sum[trie[t][1-num[i]]]) return 1;
    38             else if (!sum[trie[t][num[i]]]) return 0;
    39             else t=trie[t][num[i]];
    40         }
    41     }
    42     return 1;
    43 }
    44 int check(int x)
    45 {
    46     int i,j;
    47     for (i=0;i<=m;i++)
    48     for (j=0;j<=n;j++)
    49     flag[i][j]=0;
    50     flag[0][0]=1;
    51     for (i=1;i<=m;i++)
    52     {
    53         for (j=0;j<=tt;j++) sum[j]=0;
    54         for (j=0;j<=n;j++)
    55         {
    56             if (j-k-1>=0)
    57             if (flag[i-1][j-k-1]) add(a[j-k-1],-1);
    58             flag[i][j]=find(a[j],x);
    59             if (flag[i-1][j]) add(a[j],1);
    60         }
    61     }
    62     return flag[m][n];
    63 }
    64 int main()
    65 {
    66     int test;
    67     scanf("%d",&test);
    68     for (int ii=1;ii<=test;ii++)
    69     { 
    70     for (i=0;i<=tt;i++)
    71     trie[i][0]=trie[i][1]=0;
    72     tt=0;
    73     scanf("%d%d%d",&n,&m,&k);
    74     for (i=1;i<=n;i++)
    75     {
    76         scanf("%d",&a[i]);
    77         a[i]^=a[i-1];
    78     }
    79     for (i=0;i<=n;i++)
    80     add(a[i],0);
    81     l=1;r=2000000000;
    82     while (l<=r)
    83     {
    84         mid=(l+r)>>1;
    85         if (check(mid)) l=mid+1;else r=mid-1;
    86     }
    87     printf("Case #%d:
    ",ii); 
    88     printf("%d
    ",r);
    89     } 
    90 }
  • 相关阅读:
    CodeForces 1208 A. Boys and Girls 模拟序列
    CodeForces 1209 B. Jury Size 树状数组处理区间统计问题
    Linux环境进程间通信(转IBM)
    Qt(转IBM)
    POSIX 线程详解(转IBM)
    Perl 编程系列
    Socket in Linux(转IBM)
    Return to the Basic 限定符: const和volatile.
    SQA
    (C++)从本机获取WMI数据.
  • 原文地址:https://www.cnblogs.com/fzmh/p/5540245.html
Copyright © 2020-2023  润新知