F. Ivan and Burgers(线性基,离线)

题目链接:http://codeforces.com/contest/1100/problem/F

题目大意:首先输入n,代表当前有n个数,然后再输入m,代表m次询问,每一次询问是询问区间[l,r],这段区间内的数的最大异或值。

具体思路:贪心,我们按照右边界的大小进行排序,小的在上面,大的往下安排,然后每一次我们寻找1--> r区间内的线性基,如果当前的线性基能往后移动,我们就选取后面的这个线性基(因为我们对输入的数据进行了排序,后面的r肯定是大的,所以我们将选取的线性基尽量的往后安排肯定是没有问题的,然后我们查询的时候,看一下当前位上有线性基的时候,先判断这个线性基取的时候是从哪个数里面取出来的,然后再看一下这个数是不是大于l的,如果是的话,这个线性基就是可用的,我们通过这些线性基寻找一个最大值就可以了)

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 const int maxn =5e5+100;
 5 int sto[maxn],p[maxn],ans[maxn],ord[maxn];
 6 struct node
 7 {
 8     int l,r,id;
 9 } q[maxn];
10 bool cmp(node t1,node t2)
11 {
12     return t1.r<t2.r;
13 }
14 void add(int num,int id)
15 {
16     for(int i=20; i>=0; i--)
17     {
18         if(((1<<i)&num)==0)
19             continue;
20         if(p[i]==0)
21         {
22             p[i]=num;
23             ord[i]=id;
24             break;
25         }
26         if(ord[i]<id)//交换的时候都需要交换。
27         {
28             swap(ord[i],id);
29             swap(num,p[i]);
30         }
31         num^=p[i];
32     }
33 }
34 int query(int t)
35 {
36     int sum=0;
37     for(int i=20; i>=0; i--)
38     {
39         if(ord[i]>=t&&(sum^p[i])>sum)
40             sum^=p[i];
41     }
42     return sum;
43 }
44 int main()
45 {
46     int n,m;
47     scanf("%d",&n);
48     for(int i=1; i<=n; i++)
49     {
50         scanf("%d",&sto[i]);
51     }
52     scanf("%d",&m);
53     for(int i=1; i<=m; i++)
54     {
55         scanf("%d %d",&q[i].l,&q[i].r);
56         q[i].id=i;
57     }
58     sort(q+1,q+m+1,cmp);
59     int num=0;
60     for(int i=1; i<=m; i++)
61     {
62         while(num<q[i].r)
63             add(sto[++num],num);//将1-r都给压进去。
64         ans[q[i].id]=query(q[i].l);
65     }
66     for(int i=1; i<=m; i++)
67     {
68         printf("%d\n",ans[i]);
69     }
70     return 0;
71 }

原文地址:https://www.cnblogs.com/letlifestop/p/10269298.html

时间: 2024-11-09 03:46:41

F. Ivan and Burgers(线性基,离线)的相关文章

codeforces 1100F Ivan and Burgers 线性基 离线

题目传送门 题意: 给出 n 个数,q次区间查询,每次查询,让你选择任意个下标为 [ l , r ] 区间内的任意数,使这些数异或起来最大,输出最大值. 思路:离线加线性基. 线性基学习博客1 线性基学习博客2 对于此题,先把区间按照 r 从小到大排序,然后依次处理这些区间,每次插入线性基时,优先保留下标比较大的线性基.查询时,只异或上下标大于 l 的值. 记住异或的符号的优先级很低,所以  if( res^p[i] > res )这样的代码是会wa死的,要注意(这道题这么写,样例都过不了) #

【CF1100F】Ivan and Burgers(线性基,分治)

题意:给定n个数,每个数为c[i],有q个询问,每次询问从第l个到第r个数字的最大xor和 n,q<=5e5,c[i]<=1e6,时限3s 思路:直接线段树维护区间线性基是3个log 做法1:因为不是强制在线把询问分治能降到2个log 1 #include<bits/stdc++.h> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath>

CodeForces 1100F Ivan and Burgers

CodeForces题面 Time limit 3000 ms Memory limit 262144 kB Source Codeforces Round #532 (Div. 2) Tags data structures divide and conquer greedy math *2600 Editorial Announcement #1 (en) Announcement #2 (ru) Tutorial #1 (en) Tutorial #2 (ru) Tutorial #3 (

【bzoj4184】shallot 线段树+高斯消元动态维护线性基

题目描述 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且 让小葱从自己手中的小葱苗里选出一些小葱苗使得选出的小葱苗上的数字的异或和最大. 这种小问题对于小葱来说当然不在话下,但是他的身边没有电脑,于是他打电话给同为Oi选手的你,你能帮帮他吗? 你只需要输出最大的异或和即可,若小葱手中没有小葱苗则输出0. 输入 第一行一个正整数n表示总时间:第二行n个整数a1,a2...an,

#41 最短路(分治+线性基)

考虑异或最短路应该怎么求.那么这是个WC原题,dfs一遍找到所有有用的环丢进线性基即可,因为每一个环的权值都是可以取到且不对其他部分产生影响的. 现在给了一棵树,不妨就把他看做原图的dfs树.每增加一条边就是增加了一个环.算出权值后,现在问题变为求一个数和任选一段区间里的数的最大异或值. 比较暴力的做法是直接建线段树,每次logn*log2v取出区间线性基.这样可以拿50分. 线性基的合并实在太慢了.考虑能不能离线搞.每次取出跨过区间中点的询问,处理中点左右的后缀前缀线性基,询问时将两边线性基合

luoguP3292 [SCOI2016]幸运数字(线性基+树上倍增)

传送:https://www.luogu.org/problem/P3292 题意: $n$座城市,$n-1$条路,每个城市有一个价值$a_i$.$q$个询问,每次询问城市$x$到城市$y$的路径上经过的城市的价值的最大异或和为多少. 数据范围: $1<=n<=20000,q<=200000,a_i<=2^{60}$. 分析: 对于一次询问$x-->y$的路径上的答案,很明显就是$x-->lca(x,y)$的线性基并上$y-->lca(x,y)$的线性基,然后求最

BZOJ 3105: [cqoi2013]新Nim游戏 [高斯消元XOR 线性基]

以后我也要用传送门! 题意:一些数,选择一个权值最大的异或和不为0的集合 终于有点明白线性基是什么了...等会再整理 求一个权值最大的线性无关子集 线性无关子集满足拟阵的性质,贪心选择权值最大的,用高斯消元判断是否和已选择的线性相关 每一位记录pivot[i]为i用到的行 枚举要加入的数字的每一个二进制为1的位,如果有pivot[i]那么就异或一下(消元),否则pivot[i]=这个数并退出 如果最后异或成0了就说明线性相关... #include <iostream> #include &l

线性基 学习笔记

ps:做CF的时候碰到了一个线性基的概念,然后在网上学习了一下,发现相关的资料很少,所以打算来写一个我个人的理解. 线性代数中 有极大线性无关组和空间的基的概念.  线性基的性质与此类似. 首先来看一个问题: 给出N个数,要从中选出一个最大的子集,使得子集中的任意个元素异或值不为0. 这个和极大线性无关组有些类似.异或可以看出是模2域下的加法运算,如果把一个数转化为二进制,对应成一个由01构成的向量, 所有这些向量就构成了一个线性空间. 原问题就转化为求这个向量组的极大线性无关组,把这样一个极大

HDU 3949 XOR(线性基)

题意:给出一组数,求最小的第k个由这些数异或出来的数. 先求这组数的线性基.那么最小的第k个数显然是k的二进制数对应的线性基异或出来的数. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # includ