做法1

对于每一个询问,直接暴力在每一个序列中二分查询

时间复杂度为$o(nk)-o(k\log n)$

做法2

将所有序列合并后排序,并对每一个元素预处理出每个序列中第一个大于等于其的元素(位置),那么只需要在总序列中二分并输出该位置预处理的答案即可

关于这个预处理,显然只需要从后往前扫描一遍总序列即可

时间复杂度为$o(nk^{2})-o(k+\log nk)$

做法3

使用分治归并,并对合并后序列的每一个元素预处理出参与合并的两个序列第一个大于等于其的元素位置

对于查询,只需要在总序列中二分一次,并根据预处理的信息递归下去即可

时间复杂度为$o(nk\log k)-o(k+\log nk)$

做法4

事实上,只需要将下标为偶数的项参与合并,此时即找到第一个大于等于"其"的偶数项,再判断上一项是否大于等于"其"即可,这样查询的复杂度并没有变化

(另外,为了避免特判可以强制将最后一项也加入)

沿用做法3,并做此优化,归纳可得每一个位置上的序列长度都为$n$,复杂度即降为$o(nk)$

当然,直接沿用做法2也是可以的,即令$\{b_{k}\}=\{a_{k}\}$且$\{b_{i}\}$为$\{a_{i}\}$和$\{b_{i+1}\}$合并的结果,同样在合并后预处理相同的信息,通过此优化不难证明$\{b_{i}\}$的长度和为$o(nk)$

时间复杂度为$o(nk)-o(k+\log nk)$

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 10005
4 #define K 105
5 #define D 2
6 int n,k,m,d,x,ans,num[11],a[K][N],Pos[2],b[K][N<<1],pos[K][N<<1][2];
7 int read(){
8 int x=0;
9 char c=getchar();
10 while ((c<'0')||(c>'9'))c=getchar();
11 while ((c>='0')&&(c<='9')){
12 x=x*10+(c-'0');
13 c=getchar();
14 }
15 return x;
16 }
17 void write(int x,char c='\0'){
18 while (x){
19 num[++num[0]]=x%10;
20 x/=10;
21 }
22 if (!num[0])putchar('0');
23 while (num[0])putchar(num[num[0]--]+'0');
24 putchar(c);
25 }
26 int main(){
27 n=read(),k=read(),m=read(),d=read();
28 for(int i=1;i<=k;i++)
29 for(int j=1;j<=n;j++)a[i][j]=read();
30 for(int i=k;i;i--){
31 int x=1,y=D;
32 while ((x<=n)||(y<=b[i+1][0])){
33 if ((x<=n)&&((y>b[i+1][0])||(a[i][x]<b[i+1][y]))){
34 b[i][++b[i][0]]=a[i][x];
35 pos[i][b[i][0]][0]=x++;
36 }
37 else{
38 b[i][++b[i][0]]=b[i+1][y];
39 pos[i][b[i][0]][1]=y;
40 if (y==b[i+1][0])y+=D;
41 else y=min(y+D,b[i+1][0]);
42 }
43 }
44 memset(Pos,0,sizeof(Pos));
45 for(int j=b[i][0];j;j--)
46 for(int p=0;p<2;p++){
47 if (pos[i][j][p])Pos[p]=pos[i][j][p];
48 pos[i][j][p]=Pos[p];
49 }
50 }
51 for(int i=1;i<=m;i++){
52 x=read(),x^=ans;
53 ans=0;
54 int y=lower_bound(b[1]+1,b[1]+b[1][0]+1,x)-b[1];
55 for(int j=1;j<=k;j++){
56 if (pos[j][y][0])ans^=a[j][pos[j][y][0]];
57 if (!pos[j][y][1])break;
58 y=pos[j][y][1];
59 while ((y>1)&&(b[j+1][y-1]>=x))y--;
60 }
61 if (i%d==0)write(ans,'\n');
62 }
63 return 0;
64 }

拓展

给定一张$k$个点的DAG,每个点上有一个长为$n$的单调不下降序列$\{a_{i}\}$

$m$次询问$x$和一条路径,求出每一个路径上的序列中第一个大于等于$z$的元素

保证每一个点的入度和出度均不超过$d$

题解:

类似于做法4,在叶子上令$\{b_{leaf}\}=\{a_{leaft}\}$且$\{b_{i}\}$为$\{a_{i}\}$和$\forall (i,j)\in E,\{b_{j}\}$合并的结果(后者合并时只取下标为$d+1$的倍数的项),并预处理相同的信息

令$L_{i}$​为$i$​上序列的长度,则有$L_{i}=n+\frac{\sum_{(i,j)\in E}L_{j}}{d+1}$​,进而有
$$
\sum_{i\in V}L_{i}=\sum_{i\in V}(n+\frac{\sum_{(i,j)\in E}L_{j}}{d+1})\le \sum_{i\in V}(n+\frac{d}{d+1}L_{i})
$$
将其化简,也即$\sum_{i\in V}L_{i}\le (d+1)nk$

简单分析,可以发现预处理的时空复杂度均为$o(d\sum_{i\in V}L_{i})$,由此也即$o(d^{2}nk)$

另外,由于只取了$d+1$的倍数项,查询时最多要向前找$d$次,即最坏要找$o(dk)$次

(显然$d$要很小此做法才较优,因此二分做到$o(k\log d)$没有意义)

时间复杂度为$o(d^{2}nk)-o(dk+\log nk)$

[luogu6466]分散层叠算法的更多相关文章

  1. Note/Solution -「洛谷 P6466」分散层叠算法

    \(\mathcal{Description}\)   Link.   给定 \(m\) 个长度为 \(n\) 的有严格升序且不包含重复元素的序列 \(a_1,a_2,\cdots,a_m\),\(q ...

  2. [Comet1173]最简单的题

    称区间$[l,r]$的"信息"为其的答案和第一个.最后一个大于$x$的位置,显然通过$[l,mid]$和$[mid+1,r]$的信息可以$o(1)$合并得到$[l,r]$的信息 考 ...

  3. [loj6278]数列分块入门2

    做法1 以$K$为块大小分块,并对每一个块再维护一个排序后的结果,预处理复杂度为$o(n\log K )$ 区间修改时将整块打上标记,散块暴力修改并归并排序,单次复杂度为$o(\frac{n}{K}+ ...

  4. [cf1178G]The Awesomest Vertex

    2020年论文题,这里给出了一个$o(n\log^{2}n+m\log^{3}n)$的做法,例题3即为原题 1.例题1 题面 给定$n$个一次函数$f_{i}(x)$,$m$次查询$F(x)=\max ...

  5. 借助 SIMD 数据布局模板和数据预处理提高 SIMD 在动画中的使用效率

    原文链接 简介 为发挥 SIMD1 的最大作用,除了对其进行矢量化处理2外,我们还需作出其他努力.可以尝试为循环添加 #pragma omp simd3,查看编译器是否成功进行矢量化,如果性能有所提升 ...

  6. 前端入门4-CSS属性样式表

    本篇文章已授权微信公众号 dasu_Android(大苏)独家发布 声明 本系列文章内容全部梳理自以下四个来源: <HTML5权威指南> <JavaScript权威指南> MD ...

  7. 前端入门3-CSS基础

    本篇文章已授权微信公众号 dasu_Android(大苏)独家发布 声明 本系列文章内容全部梳理自以下四个来源: <HTML5权威指南> <JavaScript权威指南> MD ...

  8. CSS概念【记录】

    1.CSS语法 2.@规则 3.注释 4.层叠 5.优先级 6.继承 7.值 8.块格式化上下文 9.盒模型 10.层叠上下文 11.可替换元素 12.外边距合并 13.包含块 14.视觉格式化模型 ...

  9. CSS学习摘要-语法和选择器

    主要摘自网络开发者. 从最基本的层次来看,CSS是由两块内容组合而成的: 属性(Property):一些人类可理解的标识符,这些标识符指出你想修改哪一些样式,例如:字体,宽度,背景颜色等. 属性值(V ...

随机推荐

  1. 微信h5跳转小程序wx-open-launch-weapp开放标签不显示(已解决)

    前言: 前几天成功对接了跳转第三方小程序的功能,今天有个页面有需要对接.但是奇怪的是用的和上次一模一样的配置,但就是死活不显示wx-open-launch-weapp这个开放标签的按钮,看不到任何效果 ...

  2. 分布式事物SAGA

    目录 概述SAGA SAGA的执行方式 存在的问题 重试机制 SAGA VS TCC 实现SAGA的框架 概述SAGA SAGA是1987 Hector & Kenneth 发表的论文,主要是 ...

  3. 【Spring】IoC容器 - 依赖注入

    前言 上一篇文章已经学习了[依赖查找]相关的知识,这里详细的介绍一下[依赖注入]. 依赖注入 - 分类 因为自己是基于小马哥的脉络来学习,并且很认可小马哥梳理的分类方式,下面按照小马哥思想为[依赖注入 ...

  4. 【数据结构与算法Python版学习笔记】图——词梯问题 广度优先搜索 BFS

    词梯Word Ladder问题 要求是相邻两个单词之间差异只能是1个字母,如FOOL变SAGE: FOOL >> POOL >> POLL >> POLE > ...

  5. 【数据结构与算法Python版学习笔记】树——二叉查找树 Binary Search Tree

    二叉搜索树,它是映射的另一种实现 映射抽象数据类型前面两种实现,它们分别是列表二分搜索和散列表. 操作 Map()新建一个空的映射. put(key, val)往映射中加入一个新的键-值对.如果键已经 ...

  6. LCP 07.传递消息

    题目 小朋友 A 在和 ta 的小伙伴们玩传信息游戏,游戏规则如下: 有 n 名玩家,所有玩家编号分别为 0 - n-1,其中小朋友 A 的编号为 0 每个玩家都有固定的若干个可传信息的其他玩家(也可 ...

  7. 如何知道当前使用的python的安装路径

    电脑里多处安装了python,那么如何得知当前使用python的安装路径呢? 方法一 运行python指令: import sys print(sys.executable) 方法二 对于终端和Win ...

  8. 绘制PCB电路原理图的8种方法

    1.选择集成电路,变压器,晶体管等组件,这些组件体积庞大,有许多引脚并在电路中起主要作用,然后从选定的参考引脚中抽取,以减少错误. 2.如果PCB上标有元件编号(如VD870,R330,C466等), ...

  9. 洛谷 P3195 [HNOI2008] 玩具装箱

    链接: P3195 题意: 给出 \(n\) 个物品及其权值 \(c\),连续的物品可以放进一个容器,如果将 \(i\sim j\) 的物品放进一个容器,产生的费用是 \(\left(j-i+\sum ...

  10. 你一定不知道的Unsafe用法

    Unsafe是什么 首先我们说Unsafe类位于rt.jar里面sun.misc包下面,Unsafe翻译过来是不安全的,这倒不是说这个类是不安全的,而是说开发人员使用Unsafe是不安全的,也就是不推 ...