Codeforces765F. Souvenirs

$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$排序加入线段树,在线段树上二分得到。

  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\n",ans[i]);
140     return 0;
141 }
View Code

 

posted @ 2018-04-18 08:21  Blue233333  阅读(343)  评论(0编辑  收藏  举报