找到值 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&lt;&lt;1,l,m,u,v,value),getmin(id&lt;&lt;1|1,m+1,r,u,v,value))这句话就是导致TLE的原因。

如果要查找i (x&lt;=i&lt;=y)a[i]&gt;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的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ - 3489 KD树 范围计数 空间思维转换

2021牛客暑期多校训练营9 E.Eyjafjalla

二分的细节

POJ 1328 Radar Installation#贪心(坐标几何题)

如何从给定数组的范围查询中获取给定值的最小异或值

196. 质数距离