5467. 找到最接近目標值的函式值
阿新 • • 發佈:2020-07-19
題目大意
尋找陣列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; } };