51nod 1577 异或凑数(线性基)

分析:如果能知道区间线性基,问题就解决了,所以一开始有个naive的想法,搞个线性基线段树,然而复杂度(32*nlogn),果断T。。。

正解是预处理后缀线性基,并且每个基中的每一个分量位置尽量靠前,然后把k丢到左端点对应的线性基里跑,如果k最后不为0或者需要异或的位置超过了r,答案就是NO。

这样的后缀线性基可以从后面开始处理,插入x时,如果某一位已经有数且在数组中的位置在x之后,把x放入线性基替换掉这个数,然后用这个数接着跑。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define SWAP(x, y)x ^= y, y ^=x, x ^= y;
 5 using namespace std;
 6 const int maxn = 5e5 + 5, inf = 1e9;
 7 int n;
 8 struct LinearBase{
 9     int a[32], n, loca[32];
10     LinearBase(){
11         memset(a, 0, sizeof(a));
12         memset(loca, 0, sizeof(loca));
13         n = 0;
14     }
15     void insert(int x, int k){
16         int cur_loca = k;
17         int d = 31;
18         while(x && d >= 0){
19             if(x & (1 << d)){
20                 if(a[d]){
21                     if(cur_loca < loca[d]){
22                         SWAP(loca[d], cur_loca);
23                         SWAP(a[d], x);
24                     }
25                     x ^= a[d];
26                 }else{
27                     loca[d] = cur_loca;
28                     a[d] = x;
29                     n++;
30                     break;
31                 }
32             }
33             d--;
34         }
35     }
36     LinearBase operator = (LinearBase x){
37         x.n = n;
38         for(int i = 0; i < 32; i++)a[i] = x.a[i], loca[i] = x.loca[i];
39     }
40     int check(int k){
41         int d = 31, r_min = 0;
42         while(k && d>=0){
43             if(k & (1 << d)){
44                 if(!a[d])return inf;
45                 r_min = max(r_min, loca[d]);
46                 k ^= a[d];
47             }
48             d--;
49         }
50         if(k)return inf;
51         return r_min;
52     }
53 }lb[maxn];
54 int read(){
55     int ans = 0;
56     char last = ‘ ‘, ch = getchar();
57     while(ch >= ‘0‘ && ch <= ‘9‘)ans = ans * 10 + ch - ‘0‘, ch = getchar();
58     return ans;
59 }
60 bool check(int l, int r, int k){
61     LinearBase &b = lb[l];
62     if(b.check(k) <= r)return true;
63     return false;
64 }
65 int a[maxn];
66 int main(){
67 //    freopen("e:\\in.txt","r",stdin);
68     n = read();
69     for(int i = 1; i <= n; i++)a[i] = read();
70     lb[n].insert(a[n], n);
71     for(int i = n - 1; i >= 0; i--){
72         lb[i] = lb[i + 1];
73         lb[i].insert(a[i], i);
74     }
75     int m,l,r,k;
76     m = read();
77     for(int i = 0; i < m; i++){
78         l = read();r = read();k = read();
79         if(check(l, r, k))puts("YES");
80         else puts("NO");
81     }
82     return 0;
83 }
时间: 2024-10-10 07:02:08

51nod 1577 异或凑数(线性基)的相关文章

51nod 1577 异或凑数 线性基的妙用

\(OTZgengyf\)..当场被吊打\(QwQ\) 思路:线性基 提交:\(3\)次 错因:往里面加数时\(tmp.p\)与\(i\)区分不清(还是我太菜了) 题解: 我们对每个位置的线性基如此操作: 对于每一位,保存尽量靠后的数: 所以每一位还要记录位置. (后文区分"位"(二进制位)和"位置"(原数组中的第几位),每个位置都有\(30\)位) 具体来说,就是从高位向低位扫,如果我们当前的数能被放入某一位,如果这一位没有数,则直接放入:否则比较出现位置,如果当

51nod 1312 最大异或和(线性基)

线性gay - - 分析:要求和尽量大,首先可以想到,求完线性基后,记最大异或为Max,对于线性基以外的数,都可以变成Max,剩下的线性无关,变成最小线性基,可以通过异或基中最大的数把所有的最高位变成1,这样显然是最优的,然后把最大的数异或成Max,去掉这个数后再考虑剩下的数,以此类推,相当于最大的数取Max,其它的取Max ^ 自己,加起来就是答案. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring>

【XSY2701】异或图 线性基 容斥原理

题目描述 定义两个图\(G_1\)与\(G_2\)的异或图为一个图\(G\),其中图\(G\)的每条边在\(G_1\)与\(G_2\)中出现次数和为\(1\). 给你\(m\)个图,问你这\(m\)个图组成的集合有多少个子集的异或图为一个连通图. \(n\leq 10,m\leq 60\) 题解 考虑枚举图的子集划分,让被划分到不同子集的点之间没有连边,而在同一个子集里面的点可以连通,可以不连通. 可以用高斯消元(线性基)得到满足条件的图的个数.设枚举的子集划分有\(k\)个集合,那么容斥系数就

[JLOI2015]装备购买(线性基)

[JLOI2015]装备购买 题目描述 脸哥最近在玩一款神奇的游戏,这个游戏里有 nn 件装备,每件装备有 \(m\) 个属性,用向量 \(\mathbf{z_i}\)=\((a_1, \ldots ,a_j, \ldots , a_m)\) 表示 \(1 \leq i \leq n\), \(1 \leq j \leq m\),每个装备需要花费 \(c_i\) ,现在脸哥想买一些装备,但是脸哥很穷,所以总是盘算着怎样才能花尽量少的钱买尽量多的装备.对于脸哥来说,如果一件装备的属性能用购买的其他

线性基专题总结

莫(tui)名(wan)其(ti)妙(jie)又弄完了一个专题? 刚开始以为这个知识点出题都是板子来着,后来做题才发现我太天真了啊 先列知识点吧 1.性质 (1). ?原序列异或能得到的所有数都可以由线性基中的一些数异或得到 (2).?线性基里面的任意一些数异或起来都不能得到 \(0\) (3).?线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的 (4).?若线性基中有k个元素,则原序列异或能得到的数一共有 \(2^k\) 种,每种有 \(2^{n-k}\) 个 (5).?线

【BZOJ2115】【Wc2011】 Xor 线性基 异或最长路

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43410545"); } 题意:找一条异或最长路. 题解:先随便来一条路径,然后我们发现这条路径上可以随便加简单环(不管有没有共点共边). 就是因为可以先从某点走到环上来一圈再走回来,这样来去的路径被搞没了,简直污得不行. 然后我们可以用线性基来决定去

Codeforces 895C Square Subsets(状压DP 或 异或线性基)

题目链接  Square Subsets 这是白书原题啊 先考虑状压DP的做法 2到70总共19个质数,所以考虑状态压缩. 因为数据范围是70,那么我们统计出2到70的每个数的个数然后从2考虑到70. 设dp[x][mask]为考虑到x这个数的时候,x这个数和之前的所有数中,选出某些数,他们的乘积分解质因数,所有的指数对2取模之后, 状态为mask的方案数. 然后就可以转移了……这个状压DP花了我好几个小时……真是弱啊 哦对最后还要特判1的情况. 每个1选或不选都可以,然后考虑只选1的情况,累加

2017 ACM-ICPC Asia Xi&#39;an Problem A XOR(异或线性基 )

题目链接  2017西安赛区 Problem A 题意  给定一个数列,和$q$个询问,每个询问中我们可以在区间$[L, R]$中选出一些数. 假设我们选出来的这个数列为$A[i_{1}]$, $A[i_{2}]$, ..., $A[i_{t}]$ 求$K$ $or$ $($$A[i_{1}]$ $xor$ $A[i_{2}]$ ... $xor$ $A[i_{t}]$$)$的最大值 首先常规操作,每次在线段树上求出区间$[L, R]$代表的线性基. 然后把这个线性基中所有$K$的二进制表示为$

bzoj2115 [Wc2011] Xor——高斯消元 &amp; 异或线性基

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2115 异或两次同一段路径的权值,就相当于没有走这段路径: 由此可以得到启发,对于不同的走法,也许只需要找出一些东西,就可以把所有的走法用它们来异或表示出来: 再关注图上的环路,因为从 1 到 n 的不同路径也可以看作是经由 1 和 n 连接的环路,路径上也可能有环路: 发现对于环路的不同走法,就是把路与环的权值异或求最优值,重叠的部分异或了两次相当于不走: 于是问题转化为找出图上的所有环(