$n leq 100000$的数列给$m leq 300000$的询问,每次问一个区间里选两个数差的最小值。数字$leq 1e9$。
根号算法:
无脑莫队加个平衡树或者权值线段树来查前驱后继是$n sqrt{n} log_2n$的。
如果只有删除可以用链表实现,所以想办法去掉插入操作。对左端点$l$在一块$[x,y]$中的询问,可以先用链表处理出所有$i>y$的$a_i$在$[y+1,i-1]$的前驱后继,接下来只要查$[l,y]$间的数字在$[y+1,r]$中的前驱后继即可。这时把询问的$r$从大到小排序,回答每个询问的时候,左边直接删除至$y$回答询问,然后暴力把链表改回去即可。这样$m sqrt{n}$。
数据结构:
看看一个$i$会和哪些数搞起来对答案产生贡献。先找$j>i,a_j geq a_i$的,$a_j<a_i$的同理。若找$a_j geq a_i$,那么找到的数字将是个递减数列。如果数据随机,这递减数列是$log_2Max$级别长度的。但专门构造数据可以卡掉。
假如我们已经找了个$j$,要找下一个和$i$搭配能产生贡献的数,假设是$a_k,k>j$,那么有$a_i leq a_k leq a_j$,就是上面说的递减数列。除此之外,$a_k-a_i<a_j-a_k$,这啥?因为如果不满足他,$a_j$和$a_k$将比$a_i$和$a_k$优,$i$和$k$又远又大就没用了!!这样有贡献的点对就是$nlog_2Max$级别了,加个二维数点就可以$log^2$通过。
怎么找点对,可以用主席树,也可以把$a_i$排序加入线段树,在线段树上二分得到。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 //#include<time.h> 5 //#include<complex> 6 //#include<queue> 7 #include<algorithm> 8 #include<stdlib.h> 9 using namespace std; 10 11 #define LL long long 12 int qread() 13 { 14 char c; int s=0; while ((c=getchar())<'0' || c>'9'); 15 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s; 16 } 17 18 //Pay attention to '-' and LL of qread!!!! 19 20 int n,lq; 21 #define maxn 200011 22 #define maxm 1000011 23 int a[maxn]; 24 struct Poi{int v,id; bool operator < (const Poi &b) const {return v>b.v;}}p[maxn]; 25 26 struct Ques{int x,y,v; bool operator < (const Ques &b) const {return x>b.x;}}q[maxm],aa[maxn*60]; 27 int la=0; 28 29 struct SMT 30 { 31 struct Node 32 { 33 int ls,rs; 34 int Max,Min; 35 }a[maxn<<1]; 36 int size,n; 37 void up(int x) 38 { 39 Node &b=a[x],&p=a[a[x].ls],&q=a[a[x].rs]; 40 b.Max=max(p.Max,q.Max); b.Min=min(p.Min,q.Min); 41 } 42 void build(int &x,int L,int R) 43 { 44 x=++size; 45 if (L==R) {a[x].ls=a[x].rs=0; a[x].Max=-2e9; a[x].Min=2e9; return;} 46 int mid=(L+R)>>1; 47 build(a[x].ls,L,mid); build(a[x].rs,mid+1,R); up(x); 48 } 49 void build() {int x; build(x,1,n);} 50 void clear(int m) {n=m; size=0; build();} 51 int ql,qr,v; 52 void Modify(int x,int L,int R) 53 { 54 if (L==R) {a[x].Max=a[x].Min=v; return;} 55 int mid=(L+R)>>1; 56 if (ql<=mid) Modify(a[x].ls,L,mid); else Modify(a[x].rs,mid+1,R); 57 up(x); 58 } 59 void modify(int pos,int v) {ql=pos; this->v=v; Modify(1,1,n);} 60 int Query1(int x,int L,int R) 61 { 62 if (L==R) {return (L>=ql && a[x].Min<=v)?L:0;} 63 int mid=(L+R)>>1; 64 if (ql>mid) return Query1(a[x].rs,mid+1,R); 65 if (ql<=L) 66 { 67 if (a[a[x].ls].Min<=v) return Query1(a[x].ls,L,mid); 68 if (a[a[x].rs].Min<=v) return Query1(a[x].rs,mid+1,R); 69 return 0; 70 } 71 int tmp=Query1(a[x].ls,L,mid); 72 if (tmp) return tmp; 73 if (a[a[x].rs].Min<=v) return Query1(a[x].rs,mid+1,R); 74 return 0; 75 } 76 int query1(int pos,int v) {if (pos>n) return 0; ql=pos; this->v=v; return Query1(1,1,n);} 77 int Query2(int x,int L,int R) 78 { 79 if (L==R) {return (L>=ql && a[x].Max>=v)?L:0;} 80 int mid=(L+R)>>1; 81 if (ql>mid) return Query2(a[x].rs,mid+1,R); 82 if (ql<=L) 83 { 84 if (a[a[x].ls].Max>=v) return Query2(a[x].ls,L,mid); 85 if (a[a[x].rs].Max>=v) return Query2(a[x].rs,mid+1,R); 86 return 0; 87 } 88 int tmp=Query2(a[x].ls,L,mid); 89 if (tmp) return tmp; 90 if (a[a[x].rs].Max>=v) return Query2(a[x].rs,mid+1,R); 91 return 0; 92 } 93 int query2(int pos,int v) {if (pos>n) return 0; ql=pos; this->v=v; return Query2(1,1,n);} 94 }smt; 95 96 struct BIT 97 { 98 int a[maxn],n; 99 void clear(int m) {n=m; for (int i=1;i<=n;i++) a[i]=2e9;} 100 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]=min(a[x],v);} 101 int query(int x) {int ans=2e9; for (;x;x-=x&-x) ans=min(ans,a[x]); return ans;} 102 }bit; 103 104 int ans[maxm]; 105 int main() 106 { 107 n=qread(); 108 for (int i=1;i<=n;i++) a[i]=qread(); 109 lq=qread(); 110 for (int i=1;i<=lq;i++) q[i].x=qread(),q[i].y=qread(),q[i].v=i; 111 112 for (int i=1;i<=n;i++) p[p[i].id=i].v=a[i]; 113 sort(p+1,p+1+n); 114 smt.clear(n); 115 for (int i=1;i<=n;i++) 116 { 117 int id=p[i].id,v=p[i].v; 118 smt.modify(id,v); 119 int wow=2e9+1,tmp,now=id+1; 120 while (wow!=v && (tmp=smt.query1(now,(wow+0ll+v)>>1))) wow=a[tmp],aa[++la]=(Ques){id,tmp,wow-v},now=tmp+1; 121 } 122 123 smt.clear(n); 124 for (int i=n;i;i--) 125 { 126 int id=p[i].id,v=p[i].v; 127 smt.modify(id,v); 128 int wow=-1e9,tmp,now=id+1; 129 while (wow!=v && (tmp=smt.query2(now,(wow+1ll+v)>>1))) wow=a[tmp],aa[++la]=(Ques){id,tmp,v-wow},now=tmp+1; 130 } 131 132 sort(aa+1,aa+1+la); sort(q+1,q+1+lq); 133 bit.clear(n); 134 for (int i=1,j=1;i<=lq;i++) 135 { 136 while (j<=la && aa[j].x>=q[i].x) bit.add(aa[j].y,aa[j].v),j++; 137 ans[q[i].v]=bit.query(q[i].y); 138 } 139 for (int i=1;i<=lq;i++) printf("%d ",ans[i]); 140 return 0; 141 }