CodeForces 665E Beautiful Subarrays

题目:Beautiful Subarrays

链接:Here

题意:给一个数组,给一个 '完美区间' 的定义:l 到r 区间内的所有数异或和大于等于k,问给定数组有多少完美区间。

思路:

  异或运算可以前缀和处理,用w[i]表示i 前面的数异或和,那么w[5]^w[3]就是4、5两数异或的值。

  现在我们要开始建字典树了(感觉异或和字典树老扯上关系),我们从前往后一个个地把前缀加入字典树(补齐,高位补0),在w[i]加入字典树前,判断w[i]和前面的哪个前缀可以异或并且值大于等于k。这里要用树形DP,根据性质,假设高位异或后,在那一位>k在那一位的值,那就不用往下继续了,因为高位有差别,大小就已经判断出来了,直接加上所有以这个为前缀的w[i]的数量就可以了,细节小心处理,大概就是这样。

AC代码:(没整理,乱七八糟的)

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<math.h>
  5 #include<set>
  6 #include<map>
  7 #include<list>
  8 #include<stack>
  9 #include<queue>
 10 #include<vector>
 11 #include<string>
 12 #include<iostream>
 13 #include<algorithm>
 14 using namespace std;
 15 #define lson rt<<1
 16 #define rson rt<<1|1
 17 #define N 1000010
 18 #define M 100010
 19 #define Mod 1000000007
 20 #define LL long long
 21 #define INF 0x7fffffff
 22 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
 23 #define For(i,f_start,f_end) for(int i=f_start;i<f_end;i++)
 24 #define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--)
 25 #define Rep(i,f_end,f_start) for(int i=f_end;i>f_start;i--)
 26 #define MT(x,i) memset(x,i,sizeof(x))
 27 #define gcd(x,y) __gcd(x,y)
 28 const double PI = acos(-1);
 29 
 30 struct Node
 31 {
 32   int num;
 33   int next[2];
 34 }v[N*33];
 35 int vNum;
 36 
 37 int c[33],co;
 38 LL ans;
 39 
 40 void add(int x)
 41 {
 42   int bt[33],bo=0;
 43   while(x)
 44   {
 45     bt[bo++] = x&1;
 46     x>>=1;
 47   }
 48   for(int i=bo;i<33;i++)
 49   {
 50     bt[i]=0;
 51   }
 52   int p=0,i;
 53   for(i=32;i>=0;i--)
 54   {
 55     int pos = !bt[i];
 56 
 57     if(v[p].next[pos]!=-1)
 58     {
 59       if(c[i]==0) ans+=v[v[p].next[pos]].num;
 60       else
 61       {
 62         p = v[p].next[pos];
 63         if(p==-1) break;
 64         continue;
 65       }
 66     }
 67     else if(v[p].next[!pos]==-1) break;
 68     if(c[i]==1) break;
 69     p = v[p].next[!pos];
 70     if(p==-1) break;
 71   }
 72   if(i==-1) ans+=v[p].num;
 73   p=0;
 74   for(int i=32;i>=0;i--)
 75   {
 76     int pos = bt[i];
 77     if(v[p].next[pos]==-1)
 78     {
 79       v[vNum].next[0]=v[vNum].next[1]=-1;
 80       v[vNum].num=0;
 81       v[p].next[pos]=vNum++;
 82     }
 83     p = v[p].next[pos];
 84     v[p].num++;
 85   }
 86 }
 87 
 88 int w[N];
 89 int main()
 90 {
 91   int n,k,x;
 92   while(~scanf("%d%d",&n,&k))
 93   {
 94     int ttt=k;
 95     w[0]=0;
 96     for(int i=1;i<=n;i++)
 97     {
 98       scanf("%d",&x);
 99       w[i]=w[i-1]^x;
100     }
101     co=0;
102     while(k)
103     {
104       c[co++]=k&1;
105       k>>=1;
106     }
107     for(int i=co;i<33;i++) c[i]=0;
108     v[0].next[0]=v[0].next[1]=-1;
109     v[0].num=0;
110     vNum=1;
111     ans=0;
112     k=ttt;
113     for(int i=1;i<=n;i++)
114     {
115       add(w[i]);
116       if(w[i]>=k) ans++;
117     }
118     printf("%I64d\n",ans);
119   }
120   return 0;
121 }
posted @ 2016-10-09 23:10  hchlqlz  阅读(234)  评论(0编辑  收藏  举报