CodeForces - 1100F:Ivan and Burgers (线性基&贪心)(离线 在线)
题意:给定N个数,Q次询问,求区间最大异或和。
思路:一开始想的线性基+线段树。单次线性基合并的复杂度为20*20,结合线段树,复杂度为O(NlogN*20*20);显然,超时。
超时代码:
#include<bits/stdc++.h>
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep2(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=;
int a[maxn]; vector<int>G[maxn];
void read(int &x){
x=; char c=getchar();
while(c>''||c<'') c=getchar();
while(c>=''&&c<='') x=x*+c-'',c=getchar();
}
void add(vector<int>&Now,vector<int>&p)
{
rep(i,,){
int x=p[i]; if(!x) continue;
rep2(j,,){
if(x&(<<j)){
if(Now[j]) x^=Now[j];
else { Now[j]=x;break;}
}
}
}
}
void build(int Now,int L,int R)
{
rep(i,,) G[Now].pb();
if(L==R){
int x=a[L]; if(!x) return;
rep2(j,,){
if(x&(<<j)){
if(G[Now][j]) x^=G[Now][j];
else { G[Now][j]=x;break;}
}
}
return ;
}
int Mid=(L+R)>>;
build(Now<<,L,Mid); build(Now<<|,Mid+,R);
G[Now]=G[Now<<]; add(G[Now],G[Now<<|]);
}
void query(int Now,int L,int R,int l,int r,vector<int>& res)
{
if(l<=L&&r>=R) { res=G[Now]; return ;}
int Mid=(L+R)>>;
rep(i,,) res.pb();
if(l<=Mid){
vector<int>t;
query(Now<<,L,Mid,l,r,t);
res=t;
}
if(r>Mid) {
vector<int>t;
query(Now<<|,Mid+,R,l,r,t);
add(res,t);
}
}
int main()
{
int N,M,L,R; scanf("%d",&N);
rep(i,,N) read(a[i]);
build(,,N);
scanf("%d",&M);
while(M--){
read(L); read(R);
vector<int>t;
query(,,N,L,R,t);
int res=; rep2(i,,) if((res^t[i])>res) res^=t[i];
printf("%d\n",res);
}
return ;
}
我们考虑离线,把所有询问按右端点排序,然后从左到有处理询问,对于当前询问[L,R];我们把[1,R]所有的数加入线性基,关键是对于每一位,我们保留其为位置,这里肯定是贪心地保留越后面的位置越优。 那么查询的时候,如果一个线性基里的数位置>=L,则可以考虑更新答案。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep2(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=;
struct in{
int l,r,id;
friend bool operator< (in w,in v){ return w.r<v.r;}
}s[maxn];
int N,Q,ans[maxn],a[maxn],p[],pos[];
void add(int x,int id)
{
rep2(i,,)
if(x&(<<i)){
if(!p[i]){
p[i]=x; pos[i]=id;
return ;
}
if(pos[i]<id) swap(p[i],x),swap(pos[i],id);
x^=p[i];
}
}
int query(int id)
{
int res=;
rep2(i,,) if(pos[i]>=id&&(res^p[i])>res) res^=p[i];
return res;
}
int main()
{
scanf("%d",&N);
rep(i,,N) scanf("%d",&a[i]);
scanf("%d",&Q);
rep(i,,Q) scanf("%d%d",&s[i].l,&s[i].r),s[i].id=i;
sort(s+,s+Q+); int L=;
rep(i,,Q){
while(L<=s[i].r&&L<=N) add(a[L],L),++L;
ans[s[i].id]=query(s[i].l);
}
rep(i,,Q) printf("%d\n",ans[i]);
return ;
}
那么同理,不难想出在线的做法,我们纪录一个前缀和 线性基,任然保留最大的位置。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep2(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=;
int p[maxn][],pos[maxn][];
int main()
{
int N,Q,L,R,x;
scanf("%d",&N);
rep(i,,N) {
rep(j,,) p[i][j]=p[i-][j],pos[i][j]=pos[i-][j];
scanf("%d",&x); int ti=i;
rep2(j,,){
if(x&(<<j)){
if(!p[i][j]) { p[i][j]=x; pos[i][j]=ti; break; }
if(pos[i][j]<ti) swap(p[i][j],x),swap(pos[i][j],ti);
x^=p[i][j];
}
}
}
scanf("%d",&Q);
rep(i,,Q) {
scanf("%d%d",&L,&R);
int res=;
rep2(j,,) if(pos[R][j]>=L&&(res^p[R][j])>res) res^=p[R][j];
printf("%d\n",res);
}
return ;
}
CodeForces - 1100F:Ivan and Burgers (线性基&贪心)(离线 在线)的更多相关文章
- codeforces 1100F Ivan and Burgers 线性基 离线
题目传送门 题意: 给出 n 个数,q次区间查询,每次查询,让你选择任意个下标为 [ l , r ] 区间内的任意数,使这些数异或起来最大,输出最大值. 思路:离线加线性基. 线性基学习博客1 线性基 ...
- CodeForces 1100F Ivan and Burgers
CodeForces题面 Time limit 3000 ms Memory limit 262144 kB Source Codeforces Round #532 (Div. 2) Tags da ...
- BZOJ 2460 & 洛谷 P4570 [BJWC2011]元素 (线性基 贪心)
题目链接: 洛谷 BZOJ 题意 给定 \(n\) 个矿石,每个矿石有编号和魔力值两种属性,选择一些矿石,使得魔力值最大且编号的异或和不为 0. 思路 线性基 贪心 根据矿石的魔力值从大到小排序. 线 ...
- Codeforces 1100F(线性基+贪心)
题目链接 题意 给定序列,$q(1\leq q \leq 100000) $次询问,每次查询给定区间内的最大异或子集. 思路 涉及到最大异或子集肯定从线性基角度入手.将询问按右端点排序后离线处理询问, ...
- F. Ivan and Burgers(线性基,离线)
题目链接:http://codeforces.com/contest/1100/problem/F 题目大意:首先输入n,代表当前有n个数,然后再输入m,代表m次询问,每一次询问是询问区间[l,r], ...
- 【BZOJ-2460&3105】元素&新Nim游戏 动态维护线性基 + 贪心
3105: [cqoi2013]新Nim游戏 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 839 Solved: 490[Submit][Stat ...
- 【题解】 bzoj3105: [cqoi2013]新Nim游戏 (线性基+贪心)
bzoj3105,懒得复制 Solution: 首先你要有一个前置技能:如果每堆石子异或和为\(0\),则先手比输 这题我们怎么做呢,因为我们没人要先取掉几堆,为了赢对方一定会使剩下的异或和为\(0\ ...
- BZOJ.2460.[BeiJing2011]元素(线性基 贪心)
题目链接 线性基:https://blog.csdn.net/qq_36056315/article/details/79819714. \(Description\) 求一组矿石,满足其下标异或和不 ...
- [bzoj 2460]线性基+贪心+证明过程
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2460 网上很多题目都没说这个题目的证明,只说了贪心策略,我比较愚钝,在大神眼里的显然的策略 ...
随机推荐
- curl和wget的区别和使用
curl和wget基础功能有诸多重叠,如下载等. 非要说区别的话,curl由于可自定义各种请求参数所以在模拟web请求方面更擅长:wget由于支持ftp和Recursive所以在下载文件方面更擅长.类 ...
- windows配置教程
1.卸载预装软件 2.卸载非安装的预装软件 有些软件被改成了“绿色版”软件不能通过软件列表卸载,一般在C:\Program Files (x86)目录下 可以直接删除其文件夹,如果提示文件夹无法删除则 ...
- Ie11 的改变
摘录地址: http://www.4fang.net/content.jsp?id=30537 微软在上周刚刚发布了用于Windows 8.1上的首个Internet Explorer 11的 ...
- C++解析五-this 指针,指向类的指针
C++this指针 在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址.this 指针是所有成员函数的隐含参数.因此,在成员函数内部,它可以用来指向调用对象.友元函数没有 this 指 ...
- Introduction to Cryto & Crptocurrencies Lecture 1
Lecture 1.2 Hash Pointer & Data Structure Use Case 1. 什么是Block Chain呢? 想象一个像链表一样的结构,只不过与通常的指向下一块 ...
- python3 爬取简书30日热门,同时存储到txt与mongodb中
初学python,记录学习过程. 新上榜,七日热门等同理. 此次主要为了学习python中对mongodb的操作,顺便巩固requests与BeautifulSoup. 点击,得到URL https: ...
- CF712E [Memort and Casinos]
题意 每次询问一段区间[l,r],求从最左边走到最右边(r+1)的概率(若走到l-1,则GG了),每个点上写有向右走的概率.支持单点修改. 思考 若只查询一次,那只要知道每个点在不走到l-1的情况下, ...
- git-github-TortoiseGit综合使用教程(一)简介
简介: 本系列教程将参考廖雪峰的git系列教程,使用github的web界面,和TortoiseGit图形界面windows程序来实现. git 是什么: Git是目前世界上最先进的分布式版本控制系统 ...
- caffe中全卷积层和全连接层训练参数如何确定
今天来仔细讲一下卷基层和全连接层训练参数个数如何确定的问题.我们以Mnist为例,首先贴出网络配置文件: name: "LeNet" layer { name: "mni ...
- HanLP自然语言处理包介绍
支持中文分词(N-最短路分词.CRF分词.索引分词.用户自定义词典.词性标注),命名实体识别(中国人名.音译人名.日本人名.地名.实体机构名识别),关键词提取,自动摘要,短语提取,拼音转换,简繁转换, ...