zoukankan      html  css  js  c++  java
  • 5467. 找到最接近目标值的函数值

    题目大意

    寻找数组arr的区间l和r,使[l,r]区间内的数&后与target的差值的绝对值最小

    思路

    有一个很重要的推论就是&运算具有单调递减性,也就是ask(a,r+1)<=ask(l,r)<=ask(l+1,r)。因此我们可以通过滑动数组,当前区间结果>target时,r++;否则l++。
    我们用线段树维护区间&的值

    class Solution {
    public:
        static const int maxn=4*1e5+10;
        int a[maxn];
        int d[maxn];
        void build(int s,int t,int p)
        {
            //p代表线段树的结点号,s和t描述原数组的区间
            if(s==t)
            {
                d[p]=a[s];
                return;
            }
            int m=(s+t)>>1;
            build(s,m,2*p);
            build(m+1,t,2*p+1);
            d[p]=d[2*p]&d[2*p+1];
        }
        int ask(int l,int r,int s,int t,int p)
        {
            //l,r是查询区间;s,t是当前线段树的结点区间,p是线段树当前访问的结点
            if(l<=s&&r>=t)
                return d[p];
            int m=(s+t)>>1;
            if(r<=m)
                return ask(l,r,s,m,2*p);
            if(l>m)
                return ask(l,r,m+1,t,2*p+1);
            return ask(l,m,s,m,2*p)&ask(m+1,r,m+1,t,2*p+1);
        }
        int closestToTarget(vector<int>& arr, int target) {
            int n=arr.size();
            for(int i=0;i<n;i++)
                a[i]=arr[i];
            build(0,n-1,1);
            int l=0,r=0,ans=1e9+1e7;
            while(r<n)
            {
                int t=ask(l,r,0,n-1,1);
                if(t>target)
                    r++;
                else
                    l++,r=max(l,r);
                ans=min(ans,abs(t-target));
            }   
            return ans;
        }
    };
    
  • 相关阅读:
    Rolling Hash(Rabin-Karp算法)匹配字符串
    vim下单行长文本的时候卡顿解决办法
    设置vim的默认工作路径同时与自动设当前编辑的文件所在目录为当前工作路径不冲突
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
  • 原文地址:https://www.cnblogs.com/flightless/p/13340505.html
Copyright © 2011-2022 走看看