zoukankan      html  css  js  c++  java
  • [cf765F]Souvenirs

    离线,从小到大枚举右端点,维护左端点的答案,那么当右端点从$r-1$变为$r$时,即在原来的基础上考虑其中一个数为$a_{r}$的答案,并对原来的答案取$min$

    考虑另一个数为$a_{i}$,这里仅考虑$a_{r}le a_{i}$的情况($a_{r}ge a_{i}$类似):

    此时,先找到最大的$1le i_{1}<r$使得$a_{r}le a_{i_{1}}$,不妨先对$[1,i_{1}]$的答案都用$a_{i_{1}}-a_{r}$去更新

    接下来,注意到如果$a_{i_{2}}ge lceilfrac{a_{r}+a_{i_{1}}}{2} ceil$则有$|a_{i_{1}}-a_{i_{2}}|le a_{i_{2}}-a_{r}$,即其一定没有意义,那么只需要找到最大的$1le i_{2}<i_{1}$使得$a_{r}le a_{i_{2}}<lceilfrac{a_{r}+a_{i_{1}}}{2} ceil$即可

    重复此过程,即不断找到最大的$1le i_{t}<i_{t-1}$使得$a_{r}le a_{i_{t}}<lceilfrac{a_{r}+a_{i_{t-1}}}{2} ceil$,由于$0le a_{i_{t}}-a_{r}<lceilfrac{a_{t-1}-a_{r}}{2} ceil$,因此最多找$o(log V)$次,每一次用线段树维护可以做到$o(log V)$(其中$V$为值域)

    (注意查找有上下限,不能直接在线段树上二分,需要建立可持久化权值线段树来查询)

    总复杂度即$o(nlog^{2}V+mlog n)$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 #define L (k<<1)
     5 #define R (L+1)
     6 #define mid (l+r>>1)
     7 vector<pair<int,int> >v[N];
     8 int V,n,m,x,y,a[N],rt[N],mx[N*40],ls[N*40],rs[N*40],f[N<<2],ans[N<<2];
     9 void update(int k,int l,int r,int x,int y,int z){
    10     if ((l>y)||(x>r))return;
    11     if ((x<=l)&&(r<=y)){
    12         f[k]=min(f[k],z);
    13         return;
    14     }
    15     update(L,l,mid,x,y,z);
    16     update(R,mid+1,r,x,y,z);
    17 }
    18 int query(int k,int l,int r,int x){
    19     if (l==r)return f[k];
    20     if (x<=mid)return min(query(L,l,mid,x),f[k]);
    21     return min(query(R,mid+1,r,x),f[k]);
    22 }
    23 int copy(int kk){
    24     int k=++V;
    25     mx[k]=mx[kk],ls[k]=ls[kk],rs[k]=rs[kk];
    26     return k;
    27 }
    28 void update(int &k,int l,int r,int x,int y){
    29     k=copy(k);
    30     mx[k]=max(mx[k],y);
    31     if (l==r)return;
    32     if (x<=mid)update(ls[k],l,mid,x,y);
    33     else update(rs[k],mid+1,r,x,y);
    34 }
    35 int find(int k,int l,int r,int x,int y){
    36     if ((!k)||(l>y)||(x>r))return 0;
    37     if ((x<=l)&&(r<=y))return mx[k];
    38     return max(find(ls[k],l,mid,x,y),find(rs[k],mid+1,r,x,y));
    39 }
    40 int main(){
    41     scanf("%d",&n);
    42     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    43     for(int i=1;i<=n;i++)update(rt[i]=rt[i-1],0,1e9,a[i],i);
    44     memset(f,0x3f,sizeof(f));
    45     scanf("%d",&m);
    46     for(int i=1;i<=m;i++){
    47         scanf("%d%d",&x,&y);
    48         v[y].push_back(make_pair(x,i));
    49     }
    50     for(int i=1;i<=n;i++){
    51         x=find(rt[i-1],0,1e9,a[i],1e9);
    52         while (x){
    53             update(1,1,n,1,x,a[x]-a[i]);
    54             x=find(rt[x-1],0,1e9,a[i],(a[i]+a[x]-1)/2);
    55         }
    56         x=find(rt[i-1],0,1e9,0,a[i]);
    57         while (x){
    58             update(1,1,n,1,x,a[i]-a[x]);
    59             x=find(rt[x-1],0,1e9,(a[i]+a[x]+1)/2,a[i]);
    60         }
    61         for(int j=0;j<v[i].size();j++)ans[v[i][j].second]=query(1,1,n,v[i][j].first);
    62     }
    63     for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
    64 }
    View Code
  • 相关阅读:
    Class attributes
    Card objects
    Exercises
    Type-base dispatch
    Operator overloading
    The str method
    loadrunner协议开发
    nmon分析与详解
    如何判断CPU、内存、磁盘的性能瓶颈?
    用友NC客户端地址
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15012130.html
Copyright © 2011-2022 走看看