• [TC-FindingFriends]Finding Friends


    题目大意:
      给定一个长度为$n(nle10^5)$的数列$A(A_ile10^9)$,求最小的$k$满足存在一个长度至少为$m(mle n)$的子串,对于串中的每一个数$A_i$,都至少存在一个$A_j(i e j)$满足$|A_i-A_j|<k$。

    思路:
      二分答案$k$,对于每次求出每个元素$A_i$左边离$A_i$最近的满足$|A_i-A_j|<k$的$left[i]=j$,同理求出每个元素$A_j$右边离$A_i$最近的满足$|A_i-A_j|<k$的$right[i]=j$。
      考虑分治,判断区间$[l,r]$是否是满足条件的字串。
      若$r-l+1<m$则显然不满足条件。
      在$[l,r]$中找到一个下标$p$满足$left[p]<l$且$right[p]>r$,则若这样的$p$存在,则包含$p$的区间一定不满足条件,递归处理$[l,p)$和$(p,r]$。若找不到这样的$p$,则该区间满足条件,$k$为合法的答案。
      寻找$p$时,如果不是直接for而是从两端同时往里寻找,设找到的$p$两端的区间长度分别是$a$和$b$,则递归的复杂度是$O(nlog n)$(递推式$T(n)=T(a)+T(b)+min(a,b)$)。而$left$和$right$的预处理可以用线段树实现,总的时间复杂度是$O(nlog^2 n)$。

      1 #include<vector>
      2 #include<cstdio>
      3 #include<climits>
      4 #include<algorithm>
      5 class FindingFriends {
      6     private:
      7         using int64=long long;
      8         static constexpr int N=1e5+1;
      9         int n,m,lim,arr[N],tmp[N],left[N],right[N];
     10         class SegmentTree {
     11             #define _left <<1
     12             #define _right <<1|1
     13             private:
     14                 int max[N<<2],min[N<<2];
     15                 void push_up(const int &p) {
     16                     max[p]=std::max(max[p _left],max[p _right]);
     17                     min[p]=std::min(min[p _left],min[p _right]);
     18                 }
     19             public:
     20                 void reset() {
     21                     std::fill(&max[0],&max[N<<2],INT_MIN);
     22                     std::fill(&min[0],&min[N<<2],INT_MAX);
     23                 }
     24                 void modify(const int &p,const int &b,const int &e,const int &x,const int &y) {
     25                     if(b==e) {
     26                         max[p]=std::max(max[p],y);
     27                         min[p]=std::min(min[p],y);
     28                         return;
     29                     }
     30                     const int mid=(b+e)>>1;
     31                     if(x<=mid) modify(p _left,b,mid,x,y);
     32                     if(x>mid) modify(p _right,mid+1,e,x,y);
     33                     push_up(p);
     34                 }
     35                 int qmax(const int &p,const int &b,const int &e,const int &l,const int &r) {
     36                     if(b==l&&e==r) return max[p];
     37                     const int mid=(b+e)>>1;
     38                     int ret=INT_MIN;
     39                     if(l<=mid) ret=std::max(ret,qmax(p _left,b,mid,l,std::min(mid,r)));
     40                     if(r>mid) ret=std::max(ret,qmax(p _right,mid+1,e,std::max(mid+1,l),r));
     41                     return ret;
     42                 }
     43                 int qmin(const int &p,const int &b,const int &e,const int &l,const int &r) {
     44                     if(b==l&&e==r) return min[p];
     45                     const int mid=(b+e)>>1;
     46                     int ret=INT_MAX;
     47                     if(l<=mid) ret=std::min(ret,qmin(p _left,b,mid,l,std::min(mid,r)));
     48                     if(r>mid) ret=std::min(ret,qmin(p _right,mid+1,e,std::max(mid+1,l),r));
     49                     return ret;
     50                 }
     51             #undef _left
     52             #undef _right
     53         };
     54         SegmentTree t;
     55         bool check(const int &l,const int &r) {
     56             if(r-l+1<m) return false;
     57             int pos=-1;
     58             for(register int i=0;l+i<=r-i;i++) {
     59                 if(left[l+i]<l&&right[l+i]>r) {
     60                     pos=l+i;
     61                     break;
     62                 }
     63                 if(left[r-i]<l&&right[r-i]>r) {
     64                     pos=r-i;
     65                     break;
     66                 }
     67             }
     68             return pos==-1||check(l,pos-1)||check(pos+1,r);
     69         }
     70         int getlow(const int &x) const {
     71             return std::upper_bound(&tmp[1],&tmp[tmp[0]]+1,x-1)-tmp;
     72         }
     73         int getup(const int &x) const {
     74             return std::lower_bound(&tmp[1],&tmp[tmp[0]]+1,x+1)-1-tmp;
     75         }
     76         bool check(const int &k) {
     77             t.reset();
     78             for(register int i=1;i<=n;i++) {
     79                 left[i]=t.qmax(1,1,tmp[0],std::max(getlow(tmp[arr[i]]-k),1),std::min(getup(tmp[arr[i]]+k),tmp[0]));
     80                 t.modify(1,1,tmp[0],arr[i],i);
     81             }
     82             t.reset();
     83             for(register int i=n;i>=1;i--) {
     84                 right[i]=t.qmin(1,1,tmp[0],std::max(getlow(tmp[arr[i]]-k),1),std::min(getup(tmp[arr[i]]+k),tmp[0]));
     85                 t.modify(1,1,tmp[0],arr[i],i);
     86             }
     87             return check(1,n);
     88         }
     89     public:
     90         int shortestDistance(const int &nn,const std::vector<int> &init,const int &a,const int &b,const int &c,const int &d,const int &mm) {
     91             n=nn,m=mm;
     92             for(register unsigned i=0;i<init.size();i++) arr[i+1]=init[i];
     93             for(register int i=init.size();i<n;i++) {
     94                 arr[i+1]=(((int64)arr[i]*a%d+(int64)b*i%d)%d+c)%d;
     95             }
     96             lim=*std::max_element(&arr[1],&arr[n]+1);
     97             std::copy(&arr[1],&arr[n]+1,&tmp[1]);
     98             std::sort(&tmp[1],&tmp[n]+1);
     99             tmp[0]=std::unique(&tmp[1],&tmp[n]+1)-&tmp[1];
    100             for(register int i=1;i<=n;i++) {
    101                 arr[i]=std::lower_bound(&tmp[1],&tmp[tmp[0]]+1,arr[i])-tmp;
    102             }
    103             int l=0,r=lim;
    104             while(l<=r) {
    105                 const int mid=(l+r)/2;
    106                 if(check(mid)) {
    107                     r=mid-1;
    108                 } else {
    109                     l=mid+1;
    110                 }
    111             }
    112             return r+1;
    113         }
    114 };
  • 相关阅读:
    Connection parameters are correct , SSL not enabled
    log4j配置文件的详解
    java.lang.IllegalArgumentException: addChild: Child name '/SSHE' is not unique
    MYSQL的三种注释
    Oracle19c 单节点ASM 存储模式数据库实例搭建过程
    [专题]中立遭质疑,提价遭反对,ARM的生存难题怎么破?
    快速排序的理解
    chrome审查元素功能,web开发强大帮手
    MyEclipse Server view报错解决方法
    把Java程序打包成jar文件包并执行
  • 原文地址:https://www.cnblogs.com/skylee03/p/9067107.html
Copyright © 2020-2023  润新知