IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构补题 -> 正文阅读

[数据结构与算法]数据结构补题

数据结构补题

莫队

1.XOR and Favorite Number CodeForces - 617E

[题意]:
有一个数字 k 和一个长度为 n 的 a数组 。接下来有 m 次查询,每次查询会给出一对 [ L,R ] ,针对每一对L和R,求有多少对( i , j ),满足 L<=i<=j<=R 并且 ai ^ ai+1 ^… ^aj = k。

[思考]:
这道题目属于区间段异或和,所以我们容易想到用前缀和来处理,所以我们在输入的时候就可以将 a[i] 预处理为 前 i 项的前缀和。

我们使用莫队来优化查询。

如果当前已经求得的区间为 [curL , curR] ,当前区间内符合条件的答案为 num,定义一个数组 cnt,用于记录当前区间内存在的所有异或值的个数(区间在扩张的时候一直在计算),例如cnt[i] = 异或值为i的个数有 cnt[i] 个。

接下来我们来看区间扩张与收缩,以区间扩张为例,我们假定当前 右端点 curR 一定,左端点curL发生移动 ,那么我们所求的就是区间有多少个L,满足 a[curR] ^ a[L-1] =k, 等价于 a[L-1] = k^ a[curR] ,所以问题可以转化为 求 cnt[k^ a[curR]].

还有一点需要注意的是,因为对于每一个所求的 L,我们需要的是 a[L-1],所以在移动左端点的时候我们进入 函数 del 和 add 的时候需要多 - 1;
除此之外,我们还需要注意 num 变化和 cnt数组变化的先后顺序,因为本题可能存在 x==x^k 的情况,而num 值变化所需要的是 cnt[x ^ k], 所以需要处理掉 x 带来的影响,剩下的详见代码。

[代码实现]:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn= 3e6+100;
int n,q,k,a[maxn];//a[i]记录的是异或前缀和 
int curL,curR;
int len;
int st[maxn],ed[maxn],sz[maxn],blo[maxn];
ll cnt[maxn],ans[maxn];
ll num;
struct node{
	int l,r,id;
}que[maxn];
bool cmp(node a,node b){  //莫队的排序
	if(blo[a.l]!=blo[b.l]) return blo[a.l]<blo[b.l];
	return a.r<b.r;
}
void init(int n){ //分块初始化
	len=sqrt(n);
	for(int i=1;i<=len;i++){
		st[i]=n/len*(i-1)+1;
		ed[i]=n/len*i;
	}
	ed[len]=n;
	for(int i=1;i<=len;i++){
		for(int j=st[i];j<=ed[i];j++){
			blo[j]=i;
		}
	}
}
void add(int x){
	num+=cnt[a[x]^k]; //先加上 a[x]^k ,保证在 a[x]^k==a[x] 的情况下,cnt数组的是没有因为当前a[x] 进行错误更新
	cnt[a[x]]++;
}
void del(int x){
	cnt[a[x]]--; //当 a[x]^k==x ,因为cnt数组中已经包含了 a[x],所以需要将其先行减去,阻止它干扰 a[x]^k 的值
	num-=cnt[a[x]^k];
}
int main(){
	scanf("%d%d%d",&n,&q,&k);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]^=a[i-1];
	init(1100000);
	for(int i=1;i<=q;i++){
		scanf("%d%d",&que[i].l,&que[i].r);
		que[i].id=i;
	}
	sort(que+1,que+1+q,cmp);
	curL=1;
	cnt[0]++;
	for(int i=1;i<=q;i++){
		while(curL<que[i].l) del(curL-1),curL++; //处理左端点移动的时候需要多减去1
		while(curL>que[i].l) add(curL-2),--curL;
		while(curR<que[i].r) add(++curR);
		while(curR>que[i].r) del(curR--);
		ans[que[i].id]=num;
	}
	for(int i=1;i<=q;i++){
		printf("%lld\n",ans[i]);
	}
	return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-09 10:28:44  更:2021-08-09 10:30:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 21:50:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码