[luogu6466]分散层叠算法
做法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]分散层叠算法的更多相关文章
- Note/Solution -「洛谷 P6466」分散层叠算法
\(\mathcal{Description}\) Link. 给定 \(m\) 个长度为 \(n\) 的有严格升序且不包含重复元素的序列 \(a_1,a_2,\cdots,a_m\),\(q ...
- [Comet1173]最简单的题
称区间$[l,r]$的"信息"为其的答案和第一个.最后一个大于$x$的位置,显然通过$[l,mid]$和$[mid+1,r]$的信息可以$o(1)$合并得到$[l,r]$的信息 考 ...
- [loj6278]数列分块入门2
做法1 以$K$为块大小分块,并对每一个块再维护一个排序后的结果,预处理复杂度为$o(n\log K )$ 区间修改时将整块打上标记,散块暴力修改并归并排序,单次复杂度为$o(\frac{n}{K}+ ...
- [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 ...
- 借助 SIMD 数据布局模板和数据预处理提高 SIMD 在动画中的使用效率
原文链接 简介 为发挥 SIMD1 的最大作用,除了对其进行矢量化处理2外,我们还需作出其他努力.可以尝试为循环添加 #pragma omp simd3,查看编译器是否成功进行矢量化,如果性能有所提升 ...
- 前端入门4-CSS属性样式表
本篇文章已授权微信公众号 dasu_Android(大苏)独家发布 声明 本系列文章内容全部梳理自以下四个来源: <HTML5权威指南> <JavaScript权威指南> MD ...
- 前端入门3-CSS基础
本篇文章已授权微信公众号 dasu_Android(大苏)独家发布 声明 本系列文章内容全部梳理自以下四个来源: <HTML5权威指南> <JavaScript权威指南> MD ...
- CSS概念【记录】
1.CSS语法 2.@规则 3.注释 4.层叠 5.优先级 6.继承 7.值 8.块格式化上下文 9.盒模型 10.层叠上下文 11.可替换元素 12.外边距合并 13.包含块 14.视觉格式化模型 ...
- CSS学习摘要-语法和选择器
主要摘自网络开发者. 从最基本的层次来看,CSS是由两块内容组合而成的: 属性(Property):一些人类可理解的标识符,这些标识符指出你想修改哪一些样式,例如:字体,宽度,背景颜色等. 属性值(V ...
随机推荐
- FastAPI 学习之路(十一)请求体 - 嵌套模型
系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) FastAPI 学习之路(三) FastAPI 学习之路(四) FastAPI 学习之 ...
- NX7.5 使用UF_MODL_create_proj_curves创建投影曲线
1 [DllImport("libufun.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet ...
- Golang通脉之流程控制
流程控制是每种编程语言控制逻辑走向和执行次序的重要部分,流程控制可以说是一门语言的"经脉". Go语言中最常用的流程控制有if和for,而switch和goto主要是为了简化代码. ...
- Java:LinkedHashMap类小记
Java:LinkedHashMap类小记 对 Java 中的 LinkedHashMap类,做一个微不足道的小小小小记 概述 public class LinkedHashMap<K,V> ...
- java监控JVM的内存使用情况等
以下的程序监控参数的代码,有些是从网络上获取的,此处进行一个记录是为了以后如果要用到方便记录. 1.引入jar包,为了获取一些cpu的使用率等信息 <dependency> <gro ...
- IDEA注释设置:从当前鼠标位置开始注释快捷键
在写xml或html注释时,经常出现注释出来的时候都是顶格的,前面包含一大段空格,并没有在鼠标位置开始. 可在设置中进行修改,其他代码格式修改方法类似
- 21.10.9 test
T1 购票方案 \(\color{green}{100}\) 对于每个时间节点维护它作为每种票所能包含的最后一个点时,这种票的起始点位置,由于这个位置是单调的,所以类似双指针维护,\(O(KN)\) ...
- Spring Security:简单的保护一个SpringBoot应用程序(总结)
Spring Security 在 Java类中的配置 在 Spring Security 中使用 Java配置,可以轻松配置 Spring Security 而无需使用 XML . 在Spring ...
- IdentityServer4 负载均衡配置
在不用到负载之前,一切都很好,但是部署多个实例之后,问题挺多的:session问题.令牌签发后的校验问题. 在此之前,先自查官方文档:Deployment - IdentityServer4 1.0. ...
- 第02课 OpenGL 多边形
你的第一个多边形: 在第一个教程的基础上,我们添加了一个三角形和一个四边形.也许你认为这很简单,但你已经迈出了一大步,要知道任何在OpenGL中绘制的模型都会被分解为这两种简单的图形.读完了这一课,你 ...