容易想到树套树,但数据范围太大,会超时
考虑平衡树的作用,就是将这个区间内的所有数排序,所以可以离线+归并来处理,预处理复杂度$o(n\log n)$,然后考虑维护:1.删除;2.询问
删除操作维护可以使用并查集,可以通过$\alpha(n)$的时间里快速找到每一个点的上和下元素
询问操作可以二分查找,这样的复杂度为$o(q\log^{2} n+q\log n\cdot \alpha(n))$,考虑优化掉二分的复杂度:对于每一个数,合并时记录左右区间中比他小/大且最接近的数,这样只需要在最开始二分一次就可以传递下来,复杂度降为$o(q\log n\cdot \alpha(n))$
实现中可能有一些细节问题:1.$nex[k].fi.fi$表示了左子树中小于等于它的最大数,若不存在则为最小的数,若没有数就随便(在query中要判断这个区间是否存在数,而且有可能因为删除而没有数),其余同理;2.每一个数要存储个数,否则会导致存在但无法找到;3.如果最小或最大的数删掉,并查集就指向不存在的位置来表示

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 1000005
4 #define mid (l+r>>1)
5 #define L (k<<1)
6 #define R (L+1)
7 #define mp make_pair
8 #define fi first
9 #define se second
10 #define oo 0x3f3f3f3f
11 struct ji{
12 int p,l,r,k;
13 }q[N];
14 vector<int>f[N<<1],tot[N<<1],fa[2][N<<1];
15 vector<pair<pair<int,int>,pair<int,int> > >nex[N<<1];
16 int n,m,x,y,ans[N],sz[N<<1],now[N<<1];
17 int find(int p,int x,int k){
18 if ((k==sz[x])||(k==fa[p][x][k]))return k;
19 return fa[p][x][k]=find(p,x,fa[p][x][k]);
20 }
21 void add(int k,int l,int r,int x,int y){
22 now[k]++;
23 if (l==r){
24 sz[k]=1;
25 f[k].push_back(y);
26 tot[k].push_back(1);
27 return;
28 }
29 if (x<=mid)add(L,l,mid,x,y);
30 else add(R,mid+1,r,x,y);
31 }
32 void merge(int k,int l,int r){
33 if (l==r){
34 if (!sz[k])return;
35 fa[0][k].push_back(0);
36 fa[1][k].push_back(0);
37 return;
38 }
39 merge(L,l,mid);
40 merge(R,mid+1,r);
41 for(int i=0,j=0;(i<sz[L])||(j<sz[R]);){
42 fa[0][k].push_back(sz[k]);
43 fa[1][k].push_back(sz[k]++);
44 if ((i<sz[L])&&(j<sz[R])&&(f[L][i]==f[R][j])){
45 nex[k].push_back(mp(mp(i,i),mp(j,j)));
46 f[k].push_back(f[L][i]);
47 tot[k].push_back(tot[L][i++]+tot[R][j++]);
48 continue;
49 }
50 if ((i<sz[L])&&((j==sz[R])||(f[L][i]<f[R][j]))){
51 nex[k].push_back(mp(mp(i,i),mp(j-(j>0),j-((j>0)&&(j==sz[R])))));
52 f[k].push_back(f[L][i]);
53 tot[k].push_back(tot[L][i++]);
54 }
55 else{
56 nex[k].push_back(mp(mp(i-(i>0),i-((i>0)&&(i==sz[L]))),mp(j,j)));
57 f[k].push_back(f[R][j]);
58 tot[k].push_back(tot[R][j++]);
59 }
60 }
61 }
62 void del(int k,int l,int r,int x,int y){
63 now[k]--;
64 if (--tot[k][y]==0){
65 if (!y)fa[0][k][y]=sz[k];
66 else fa[0][k][y]=fa[0][k][y-1];
67 if (y==sz[k]-1)fa[1][k][y]=sz[k];
68 else fa[1][k][y]=fa[1][k][y+1];
69 }
70 if (l==r)return;
71 if (x<=mid)del(L,l,mid,x,nex[k][y].fi.fi);
72 else del(R,mid+1,r,x,nex[k][y].se.fi);
73 }
74 int query(int k,int l,int r,int x,int y,int z,int a,int b){
75 if ((l>y)||(x>r)||(!now[k]))return oo;
76 if ((x<=l)&&(r<=y)){
77 int ans=oo;
78 if (find(0,k,a)<sz[k])ans=min(ans,abs(z-f[k][find(0,k,a)]));
79 if (find(1,k,b)<sz[k])ans=min(ans,abs(z-f[k][find(1,k,b)]));
80 return ans;
81 }
82 return min(query(L,l,mid,x,y,z,nex[k][a].fi.fi,nex[k][b].fi.se),query(R,mid+1,r,x,y,z,nex[k][a].se.fi,nex[k][b].se.se));
83 }
84 int main(){
85 scanf("%d%d",&n,&m);
86 for(int i=1;i<=m;i++){
87 scanf("%d%d",&q[i].p,&q[i].l);
88 if (q[i].p)scanf("%d%d",&q[i].r,&q[i].k);
89 else{
90 scanf("%d",&q[i].k);
91 add(1,1,n,q[i].l,q[i].k);
92 }
93 }
94 merge(1,1,n);
95 for(int i=m;i;i--)
96 if (!q[i].p)del(1,1,n,q[i].l,lower_bound(f[1].begin(),f[1].end(),q[i].k)-f[1].begin());
97 else{
98 x=upper_bound(f[1].begin(),f[1].end(),q[i].k)-f[1].begin()-1;
99 y=lower_bound(f[1].begin(),f[1].end(),q[i].k)-f[1].begin();
100 ans[++ans[0]]=query(1,1,n,q[i].l,q[i].r,q[i].k,max(x,0),y);
101 }
102 for(int i=ans[0];i;i--)
103 if (ans[i]==oo)printf("-1\n");
104 else printf("%d\n",ans[i]);
105 }

[noi1774]array的更多相关文章

  1. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  2. ES5对Array增强的9个API

    为了更方便的对Array进行操作,ES5规范在Array的原型上新增了9个方法,分别是forEach.filter.map.reduce.reduceRight.some.every.indexOf ...

  3. JavaScript Array对象

    介绍Js的Array 数组对象. 目录 1. 介绍:介绍 Array 数组对象的说明.定义方式以及属性. 2. 实例方法:介绍 Array 对象的实例方法:concat.every.filter.fo ...

  4. 了解PHP中的Array数组和foreach

    1. 了解数组 PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.详细的解释可参见:PHP.net中的Array数组    . 2.例子:一般的数组 这里,我 ...

  5. 关于面试题 Array.indexof() 方法的实现及思考

    这是我在面试大公司时碰到的一个笔试题,当时自己云里雾里的胡写了一番,回头也曾思考过,最终没实现也就不了了之了. 昨天看到有网友说面试中也碰到过这个问题,我就重新思考了这个问题的实现方法. 对于想进大公 ...

  6. javascript之活灵活现的Array

    前言 就如同标题一样,这篇文章将会灵活的运行Array对象的一些方法来实现看上去较复杂的应用. 大家都知道Array实例有这四个方法:push.pop.shift.unshift.大家也都知道 pus ...

  7. 5.2 Array类型的方法汇总

    所有对象都具有toString(),toLocaleString(),valueOf()方法. 1.数组转化为字符串 toString(),toLocaleString() ,数组调用这些方法,则返回 ...

  8. OpenGL ES: Array Texture初体验

    [TOC] Array Texture这个东西的意思是,一个纹理对象,可以存储不止一张图片信息,就是说是是一个数组,每个元素都是一张图片.这样免了频繁地去切换当前需要bind的纹理,而且可以节省系统资 ...

  9. Merge Sorted Array

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note:Yo ...

随机推荐

  1. Pytorch学习2020春-1-线性回归

    线性回归 主要内容包括: 线性回归的基本要素 线性回归模型从零开始的实现 线性回归模型使用pytorch的简洁实现 线性回归的基本要素 模型 为了简单起见,这里我们假设价格只取决于房屋状况的两个因素, ...

  2. Java基础之(二):Notepad++实现HelloWorld

    现在我们开始编写我们的第一个程序:Hello World! HelloWorld 新建一个java文件 文件后缀名为.java Hello.java 代码分析: 接下来写完最大的框之后,那接下来当然就 ...

  3. 常用SQL函数大全

    数学函数 mod(x,y) 返回x/y的模(余数)mod(5,3)=2,mod(3,5)=3 floor(x)   返回小于x的最大整数值ceiling(3)=3,ceiling(3.1)=3 cei ...

  4. 蝉知CMS 7.X XSS漏洞复现

    个人博客地址:xzajyjs.cn 作为一个开源的企业门户系统(EPS), 企业可以非常方便地搭建一个专业的企业营销网站,进行宣传,开展业务,服务客户.蝉知系统内置了文章.产品.论坛.评论.会员.博客 ...

  5. 小甲鱼零基础学python第25讲课后习题动手练习--通讯录

    小甲鱼零基础学python第25讲课后习题动手练习---通讯录 **************************通讯录要求******************************* 输入指令: ...

  6. JAVA复习总体大纲

    1 java基础. [1].变量--- 数据类型 变量名=值; 数据类型: 1.基本数据类型. byte[1字节] short[2字节] int[4字节] long[8字节] float[4字节] d ...

  7. [对对子队]会议记录4.21(Scrum Meeting12)

    今天已完成的工作 吴昭邦 ​ 工作内容:基本实现改变顺序合成 ​ 相关issue:实现流水线合成系统的逻辑 ​ 相关签入:4.21签入1 梁河览 ​ 工作内容:修改设置界面bug ​ 相关签入:4.2 ...

  8. JAVA实现表达式求导运算的分析总结

    1第一次作业 1.1题目描述 对形如4*x+x^2+x的多项式求导. 1.2类图 1.3度量分析 在完成第一次作业时,我的写法没有特别的"面向对象".唯一封装起来的是Node,代表 ...

  9. 零基础学习C语言入门必备知识

    今天跟大家一起从零学C语言: 1. C语言简介 1.1 C语言发展史 C语言是一种广泛使用的面向过程的计算机程序设计语言,既适合于系统程序设计,又适合于应用程序设计.C语言的发展历程大致如图1-1所示 ...

  10. 零基础学习Linux必会的60个常用命令

    Linux必学的60个命令Linux提供了大量的命令,利用它可以有效地完成大量的工 作,如磁盘操作.文件存取.目录操作.进程管理.文件权限设定等.所以,在Linux系统上工作离不开使用系统提供的命令. ...