【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>
  6 #include<iostream>
  7 #include<algorithm>
  8 #include<map>
  9 #include<set>
 10 #include<queue>
 11 #include<vector>
 12 #include<bitset>
 13 using namespace std;
 14 typedef long long ll;
 15 typedef unsigned int uint;
 16 typedef unsigned long long ull;
 17 typedef pair<int,int> PII;
 18 typedef vector<int> VI;
 19 typedef set<int>::iterator iter;
 20 #define fi first
 21 #define se second
 22 #define MP make_pair
 23 #define mem0(a) memset(a,0,sizeof(a))
 24 #define N      510000
 25 #define M      15
 26 #define MOD 1000000007
 27 #define eps 1e-10
 28 #define pi     acos(-1)
 29 #define oo     1e9
 30  
 31 int read()
 32 {
 33    int v=0,f=1;
 34    char c=getchar();
 35    while(c<48||57<c) {if(c==‘-‘) f=-1; c=getchar();}
 36    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 37    return v*f;
 38 }
 39  
 40 struct base
 41 {
 42     //ll d[20],p[20];
 43     int d[20];
 44     int cnt;
 45
 46     base()
 47     {
 48         memset(d,0,sizeof(d));
 49         //memset(p,0,sizeof(p));
 50         cnt=0;
 51     }
 52     bool insert(int val)
 53     {
 54         if(val==0) return 0;
 55         for(int i=20;i>=0;i--)
 56          if((val>>i)&1)
 57             {
 58                 if(!d[i])
 59                 {
 60                     d[i]=val;
 61                     break;
 62                 }
 63                 val^=d[i];
 64             }
 65         return val>0;
 66     }
 67     int query_max()
 68     {
 69         int ret=0;
 70         for(int i=20;i>=0;i--) ret=max(ret,ret^d[i]);
 71         return ret;
 72     }
 73     int query_min()
 74     {
 75         for(int i=0;i<=20;i++)
 76          if(d[i]) return d[i];
 77         return 0;
 78     }
 79     /*void rebuild()
 80     {
 81         for(int i=20;i>=0;i--)
 82          for(int j=i-1;j>=0;j--)
 83           if((d[i]>>j)&1) d[i]^=d[j];
 84         for(int i=0;i<=20;i++)
 85          if(d[i]) p[cnt++]=d[i];
 86     }
 87     ll kthquery(ll k)
 88     {
 89         int ret=0;
 90         if(k>=(1LL<<cnt)) return -1;
 91         for(int i=20;i>=0;i--)
 92          if((k>>i)&1) ret^=p[i];
 93         return ret;
 94     }*/
 95
 96     base operator+(const base&_A)const
 97     {
 98         base ret=*this;
 99         for(int i=20;i>=0;i--)
100          if(_A.d[i]) ret.insert(_A.d[i]);
101         return ret;
102     }
103 }t[N],b;
104  
105 struct arr
106 {
107     int x,y,id;
108 }q[N],c[N];
109  
110 int a[N],ans[N];
111
112 /*base merge(const base &n1,const base &n2)
113 {
114     base ret=n1;
115     for(int i=20;i>=0;i--)
116      if(n2.d[i]) ret.insert(n1.d[i]);
117     return ret;
118 }*/
119  
120 void solve(int l,int r,int x,int y)
121 {
122     if(l==r)
123     {
124         for(int i=x;i<=y;i++) ans[q[i].id]=a[l];
125         return;
126     }
127     if(x>y) return;
128     int mid=(l+r)>>1;
129     memset(b.d,0,sizeof(b.d));
130     for(int i=mid;i>=l;i--)
131     {
132         b.insert(a[i]);
133         for(int j=0;j<=20;j++) t[i].d[j]=b.d[j];
134     }
135     memset(b.d,0,sizeof(b.d));
136     for(int i=mid+1;i<=r;i++)
137     {
138         b.insert(a[i]);
139         for(int j=0;j<=20;j++) t[i].d[j]=b.d[j];
140     }
141     int l1=x,r1=y;
142     for(int i=x;i<=y;i++)
143     {
144         if(q[i].y<=mid) c[l1++]=q[i];
145          else if(q[i].x>mid) c[r1--]=q[i];
146           else
147           {
148                   base tmp=t[q[i].x]+t[q[i].y];
149                 ans[q[i].id]=tmp.query_max();
150           }
151     }
152     for(int i=x;i<l1;i++) q[i]=c[i];
153     for(int i=r1+1;i<=y;i++) q[i]=c[i];
154     solve(l,mid,x,l1-1);
155     solve(mid+1,r,r1+1,y);
156 }
157  
158 int main()
159 {
160     //freopen("cf1100f.in","r",stdin);
161     //freopen("cf1100f.out","w",stdout);
162     int n,m;
163     scanf("%d",&n);
164     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
165     scanf("%d",&m);
166     for(int i=1;i<=m;i++)
167     {
168         scanf("%d%d",&q[i].x,&q[i].y);
169         q[i].id=i;
170     }
171     solve(1,n,1,m);
172     for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
173     return 0;
174 }

原文地址:https://www.cnblogs.com/myx12345/p/11438800.html

时间: 2024-11-04 07:15:14

【CF1100F】Ivan and Burgers(线性基,分治)的相关文章

codeforces 1100F Ivan and Burgers 线性基 离线

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

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

题目链接:http://codeforces.com/contest/1100/problem/F 题目大意:首先输入n,代表当前有n个数,然后再输入m,代表m次询问,每一次询问是询问区间[l,r],这段区间内的数的最大异或值. 具体思路:贪心,我们按照右边界的大小进行排序,小的在上面,大的往下安排,然后每一次我们寻找1--> r区间内的线性基,如果当前的线性基能往后移动,我们就选取后面的这个线性基(因为我们对输入的数据进行了排序,后面的r肯定是大的,所以我们将选取的线性基尽量的往后安排肯定是没

[BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)

4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2131  Solved: 865[Submit][Status][Discuss] Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一些旅行者希望游览 A 国.旅行者计划 乘飞机降落在 x 号城市,沿着 x

【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路的两端都是城市(可能两端是同一个城市),保证任意两个城市都可以通过高速公路互达. 国正在筹划“八纵八横”的高铁建设计划,计划要修建一些高速铁路,每条高速铁路两端也都是城市(可能两端是同一个城市),也都有一个非负整数的经济影响因子.国家还计划在“八纵八横”计划建成之后,将“一带一路”扩展为“一带_路一

loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)

题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se second #define pb push_back #define bit bitset<B + 1> using namespace std; const int MAXN = 501, B = 1001, SS = 4001; inline int read() { char c = getchar

HAOI2017 八纵八横——线段树分治+线性基

题目大意 给定一个图,每次加一些边,或者删掉一些后来加上去的边,定义一个环的价值为环上所有的边的异或和,重复走的边重复算.每次询问这个时刻图中的所有经过1号点的环的最大价值. 思路 首先考虑对于一个静态的图如何求解图中所有经过1号点的环的最大价值,发现这个经过1号点就是唬人的,图中任意一个环都可以经过1号点再走回来. 于是题目变成了求解图中环的最大价值,可以将图中所有的简单环给拎出来放到线性基里面求最大价值,不难发现这是对的. 然后题目转化为了如何求图中所有的简单环,一般我们可以直接对图dfs找

Codeforces 938G 线段树分治 线性基 可撤销并查集

Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问x到y的路径异或最小值 保证图在任意时刻连通 首先连通图路径异或相当于从x到y的任意一条路径再异或上若干个环得到的,只要在dfs过程中把非树边成的环丢到线性基里就好了,其他环一定可以通过这些环异或组合出来 有加边删边操作怎么做呢?线段树时间分治!注意到不能保证在线段树的任意一个节点图是连通的,需要用

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

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

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 (