找到值 a[x]>u 在 [l,r] 范围内的第一个索引 x
Posted
技术标签:
【中文标题】找到值 a[x]>u 在 [l,r] 范围内的第一个索引 x【英文标题】:Find the first index x that the value a[x]>u in range [l,r] 【发布时间】:2021-10-16 13:41:44 【问题描述】:给定一个 数组 a[] 有 n 个非负元素。我们有两种类型的查询:
A x y v:找到a[i]>v
的第一个索引i(xB u v:更新 a[u]=v;我使用分段树,但在某些测试中它是 TLE。
这是我的代码。
it max(it A,it B)
it C;
C.mx=max(A.mx,B.mx);
return C;
这是构建第一棵树的函数。
void build(int id,int l,int r)
if(l==r)
st[id].mx=a[l];
st[id].pos=l;
return;
int m=l+r>>1;
build(id<<1,l,m);
build(id<<1|1,m+1,r);
st[id]=max(st[id<<1],st[id<<1|1]);
更新查询:
void update(int id,int l,int r,int u,int v)
if(u<l||r<u) return;
if(l==r)
st[id].mx=v;
return;
int m=l+r>>1;
update(id<<1,l,m,u,v);
update(id<<1|1,m+1,r,u,v);
st[id]=max(st[id<<1],st[id<<1|1]);
“查找”查询:
int getmin(int id,int l,int r,int u,int v,int value)
if(v<l||r<u) return 1e9;
if(l==r)
return st[id].pos;
int m=l+r>>1;
//cout<<"->"<<id<<" "<<l<<" "<<r<<endl;
if(st[id<<1].mx<=value)
if(st[id<<1|1].mx<=value)
return 1e9;
else return getmin(id<<1|1,m+1,r,u,v,value);
else
if(st[id<<1|1].mx<=value)
return getmin(id<<1,l,m,u,v,value);
else return min(getmin(id<<1,l,m,u,v,value),getmin(id<<1|1,m+1,r,u,v,value));
【问题讨论】:
【参考方案1】:您的问题的查询是“查找第一个索引 i”,但是您的代码 getmin
在 [x,y] 中找到了 minimun val > v。
这就是你的预期? return min(getmin(id<<1,l,m,u,v,value),getmin(id<<1|1,m+1,r,u,v,value))
这句话就是导致TLE的原因。
如果要查找i (x<=i<=y)
和a[i]>v
的第一个索引,请使用下面的代码(取消选中)来获取一个区间内的最大值,而不是使用二进制搜索来查找第一个索引。
int getMax(int id,int l,int r,int x,int y)
if(x <= l && r <= y) return st[id].mx;
if(l > y || r < x) return -1e9;
int m=l+r>>1;
return max(getMax(id<<1,l,m,x,y), getMax(id<<1|1,m+1,r,x,y));
/*
* ROOT is the root of the segtree.
* L,R are the index bound of segtree.
* return -1 if no such element.
* */
int getFirstIndex(int x, int y, int v)
if(getMax(ROOT, L, R, x, y) <= v) return -1;
int mid = -1;
while(x <= y)
mid = (x + y) >> 1;
if(getMax(ROOT,L,R,x, mid) > v)
y = mid - 1;
else
x = mid + 1;
return x;
【讨论】:
以上是关于找到值 a[x]>u 在 [l,r] 范围内的第一个索引 x的主要内容,如果未能解决你的问题,请参考以下文章