标签:return 函数 int 线段 ++ ask 5467 目标值 target
题目大意
寻找数组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;
}
};
标签:return,函数,int,线段,++,ask,5467,目标值,target 来源: https://www.cnblogs.com/flightless/p/13340505.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。