bzoj5092: [Lydsy1711月赛]分割序列

【题解】

  理解得迷迷糊糊。。。

  一些准备操作就不说了吧。。

  首先对于当前的第i个数,贪心思想按二进制位从高到低考虑。

  若当前第j位是1,不管异或0还是1,这一位的贡献肯定是1<<j,不考虑??

  对于当前位是0的情况,你只要考虑是否有数 包含 前面几位高位的被异或出来的1 的情况下,当前位也是1,那么就异或上当前的1,加上当前的1的贡献,也就是答案加上2<<j。

  这里有个细节,处理第j位的时候,先不用管低位是否被影响到(可以思考一下)。

  主要是考虑怎么求出是否有满足条件的数。

  这个只要预处理出一个数组f[sta],表示状态集包含sta的出现最早的位置,对于之后关于第i位的一些询问,只要判断是否f[sta]<=i就行,也就是寻求的数是否在i之前出现。(dp一下即可)

 

 

  我也不知道我在讲什么。。

【代码】

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int N=300005;
 6 const int S=1100005;
 7 int n,x,now;
 8 int f[S],a[N];
 9 int main()
10 {
11     scanf("%d",&n);
12     memset(f,0x3f,sizeof(f));
13     f[0]=0;
14     for (int i=1;i<=n;++i)
15     {
16         scanf("%d",&a[i]);
17         a[i]^=a[i-1];
18         f[a[i]]=min(f[a[i]],i);
19     }
20     for (int i=0;i<20;++i)
21         for (int j=0;j<1<<20;++j)
22             if (!(j>>i&1))    f[j]=min(f[j],f[j|1<<i]);
23     for (int i=1;i<=n;++i)
24     {
25         now=0;
26         for (int j=19;~j;--j)
27             if (!(a[i]>>j&1) && f[now|1<<j]<=i)    now|=1<<j;
28         printf("%d\n",now+now+a[i]);
29     }
30     return 0;
31 }
View Code

 

posted @ 2018-03-27 18:55  Bleacher  阅读(131)  评论(1编辑  收藏