Range Minimum Queries

这篇博客探讨了如何处理Range Minimum Queries的问题,利用线段树进行优化。文章通过一个例子展示了在处理0型查询(查找指定范围内最小值)和1型查询(对指定范围内的元素进行位与赋值操作)时,如何有效地更新线段树。关键在于将问题转化为二进制表示,只更新那些在当前状态下为0的位,从而减少不必要的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

You are given an array of N integers. You should support the following queries on this array.

  • 0 L R : Find the minimum integer in the range AL, AL+1, ..., AR.
  • 1 L R X : You should apply the assignment A[i] = A[i] & X, for all indices i in range [L, R], where & denotes bitwise AND operation.

Input

First line of the input contains two space separated integers N and Q.

Second line contains N integer numbers denoting array A.

In the next Q lines, each contain one of the queries described above.

Output

For each query of the type 0, output a single line containing the answer of the query.

Constraints

  • 1 ≤ N, Q ≤ 105
  • 1 ≤ AiX ≤ 109
  • 1 ≤ L ≤ R ≤ N

Example

Input:
5 5
1 5 2 3 4
0 2 5
1 1 5 6
0 2 2
1 2 5 3
0 1 3

Output:
2
4
0
中文题意请看这里:

https://odzkskevi.qnssl.com/e9034bc038dcbe22b7b4894298e69c38?v=1497576044

线段树。重点在于更新上。一开始只是简单的想当前值为0,就没必要更新了。想的太过简单了。再深入一步想,应该转化成二进制,看哪一位上是0,就没有必要再更新了。这样就能得到更大的优化,因为每个点最多更新30次。

用一个变量state来记录当前区间的二进制状态。更新的时候,如果要更新的当前状态位上是0,则返回。

剩下的看代码吧。

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>

using namespace std;
const int MAXN = 1e5+7;
int n,m;
struct node
{
    int l,r;
    int MIN;
    int state;
}tree[MAXN<<2];
void push_up(int i)
{
    tree[i].state = tree[i<<1].state | tree[i<<1|1].state;
    tree[i].MIN = tree[i<<1].MIN<tree[i<<1|1].MIN?tree[i<<1].MIN:tree[i<<1|1].MIN;
}
void build_tree(int i,int l,int r)
{
    tree[i].l = l ;
    tree[i].r = r;
    if(l == r)
    {
        scanf("%d",&tree[i].MIN);
        tree[i].state = tree[i].MIN;
        return ;
    }
    int mid = (l+r)>>1;
    build_tree(i<<1,l,mid);
    build_tree(i<<1|1,mid+1,r);
    push_up(i);
}
void updata(int i,int l,int r,int x)
{
    if((tree[i].state & x) == 0)return;
    if(tree[i].l == tree[i].r)
    {
        tree[i].MIN -= x;
        tree[i].state -= x;
        return ;
    }
    int mid = (tree[i].l+tree[i].r)>>1;
    if(r <= mid)updata(i<<1,l,r,x);
    else if(l > mid)updata(i<<1|1,l,r,x);
    else
    {
        updata(i<<1,l,mid,x);
        updata(i<<1|1,mid+1,r,x);
    }
    push_up(i);
}
int ask(int i,int l,int r)
{
    if(tree[i].l == l && tree[i].r == r)return tree[i].MIN;
    int mid = (tree[i].l + tree[i].r)>>1;
    if(r <= mid)return ask(i<<1,l,r);
    else if(l > mid)return ask(i<<1|1,l,r);
    else return min(ask(i<<1,l,mid),ask(i<<1|1,mid+1,r));

}


int main()
{
    scanf("%d%d",&n,&m);
    build_tree(1,1,n);
    int x,l,r,y;
    while(m--)
    {
        scanf("%d%d%d",&x,&l,&r);
        if(!x)printf("%d\n",ask(1,l,r));
        else
        {
            scanf("%d",&y);
            int t = 1;
            for(int i = 0 ; i < 30 ; ++i)
            {
                if((y & 1) == 0)updata(1,l,r,t);
                y >>= 1;
                t <<= 1;
            }
        }
    }
    return 0;
}






from face_tracking import servos from maix import image, camera, display, time, nn, touchscreen ### model path MODEL = "/root/models/retinaface.mud" class Target: """Obtain the error value between the target and the center point. Need to modify __init__() and __get_target(). Args: out_range (float): output range ignore_limit (float): dead zone path (str): model path """ def __init__(self, out_range:float, ignore_limit:float, path:str): """Constructor Initialization of the recognition model class or other classes needs to be implemented here. """ self.pitch = 0 self.roll = 0 self.out_range = out_range self.ignore = ignore_limit ### Self.w and self.h must be initialized. self.detector = nn.Retinaface(model=path) self.w = self.detector.input_width() self.h = self.detector.input_height() self.cam = camera.Camera(self.w, self.h) self.disp = display.Display() ### The following section is used as an opt-out and normally you do not need to modify it. self.ts = touchscreen.TouchScreen() self.img_exit = image.load("./assets/exit.jpg").resize(40, 40) self.img_exit_touch = image.load("./assets/exit_touch.jpg").resize(40, 40) self.box = [0, 0, self.img_exit.width(), self.img_exit.height()] self.need_exit = False def __check_touch_box(self, t, box, oft = 0): """This method is used for exiting and you normally do not need to modify or call it. You usually don't need to modify it. """ if t[2] and t[0] + oft > box[0] and t[0] < box[0] + box[2] + oft and t[1] + oft > box[1] and t[1] < box[1] + box[3] + oft: return True else: return False def __exit_listener(self, img): """Exit case detection methods. It also draws the Exit button in the upper left corner. You usually don't need to modify it. Args: img (image.Image): The image that needs to be drawn. """ t = self.ts.read() if self.__check_touch_box(t, self.box, 20): img.draw_image(self.box[0], self.box[1], self.img_exit_touch) self.need_exit = True else: img.draw_image(self.box[0], self.box[1], self.img_exit) def is_need_exit(self): """Queries whether the exit button has been pressed. You usually don't need to modify it. Returns: bool: Returns true if the exit button has been pressed, false otherwise. """ return self.need_exit def __get_target(self): """Get the coordinate value of the target. The behavior of this function needs to be customized. Returns: int, int: If no target is found, return -1,-1. If the target is found, return the coordinate values x,y of the center point of the target. """ ltime = time.ticks_ms() img = self.cam.read() # Reads an image frame. objs = self.detector.detect(img, conf_th = 0.4, iou_th = 0.45) # Recognition. for obj in objs: # Find objects. img.draw_rect(obj.x, obj.y, obj.w, obj.h, image.COLOR_RED, 2) cent_x = obj.x + round(obj.w/2) # Calculate the x-coordinate of the target center point. cent_y = obj.y + round(obj.h/2) # Calculate the y-coordinate of the target center point. img.draw_rect(cent_x-1, cent_y-1, 2, 2, image.COLOR_GREEN) rtime = time.ticks_ms() # print(f"find target used time:{round(rtime-ltime,2)}ms") self.__exit_listener(img) # Queries whether the Exit button was pressed. self.disp.show(img) # Display this image. return cent_x, cent_y # Return (x, y) self.__exit_listener(img) self.disp.show(img) return -1, -1 # Target not found. Return (-1, -1) def get_target_err(self): """Obtain the error value between the target and the center point. You usually don't need to modify it. Returns: int, int: y-axis error value, x-axis error value. """ cent_x, cent_y = self.__get_target() if cent_x == -1: return (0, 0) self.pitch = cent_y / self.h * self.out_range * 2 - self.out_range self.roll = cent_x / self.w * self.out_range * 2 - self.out_range if abs(self.pitch) < self.out_range*self.ignore: self.pitch = 0 if abs(self.roll) < self.out_range*self.ignore: self.roll = 0 return self.pitch, self.roll if __name__ == '__main__': ROLL_PWM_PIN_NAME = "A17" PITCH_PWM_PIN_NAME = "A16" init_pitch = 150 # init position, value: [0, 100], means minimum angle to maxmum angle of servo init_roll = 150 # 50 means middle PITCH_DUTY_MIN = 3.5 # The minimum duty cycle corresponding to the range of motion of the y-axis servo. PITCH_DUTY_MAX = 9.5 # Maximum duty cycle corresponding to the y-axis servo motion range. ROLL_DUTY_MIN = 2.5 # Minimum duty cycle for x-axis servos. ROLL_DUTY_MAX = 12.5 # Maxmum duty cycle for x-axis servos. pitch_pid = [0.3, 0.0001, 0.0018, 0] # [P I D I_max] roll_pid = [0.3, 0.0001, 0.0018, 0] # [P I D I_max] target_err_range = 10 # target error output range, default [0, 10] target_ignore_limit = 0.08 # when target error < target_err_range*target_ignore_limit , set target error to 0 pitch_reverse = False # reverse out value direction roll_reverse = True # reverse out value direction target = Target(target_err_range, target_ignore_limit, MODEL) try: roll = servos.Servos(ROLL_PWM_PIN_NAME, init_roll, ROLL_DUTY_MIN, ROLL_DUTY_MAX) pitch = servos.Servos(PITCH_PWM_PIN_NAME, init_pitch, PITCH_DUTY_MIN, PITCH_DUTY_MAX) except RuntimeError as e: print(f"!!!!!!!!!!!!!!!! ERROR: {e} !!!!!!!!!!!!!!!!!!!!!!") wait_time_s = 10 while wait_time_s: eimg = image.Image(target.w, target.h) eimg.draw_string(10, 10, "Error: "+str(e)+ f". This program will exit after {wait_time_s}s.") target.disp.show(eimg) time.sleep(1) wait_time_s -= 1 exit(-1) pid_pitch = servos.PID(p=pitch_pid[0], i=pitch_pid[1], d=pitch_pid[2], imax=pitch_pid[3]) pid_roll = servos.PID(p=roll_pid[0], i=roll_pid[1], d=roll_pid[2], imax=roll_pid[3]) gimbal = servos.Gimbal(pitch, pid_pitch, roll, pid_roll) total_uesd_time = 0 total_fps = 0 t0 = time.ticks_ms() while not target.is_need_exit(): ltime = time.ticks_ms() # get target error err_pitch, err_roll = target.get_target_err() # interval limit to >= 10ms if time.ticks_ms() - t0 < 10: continue t0 = time.ticks_ms() # run gimbal.run(err_pitch, err_roll, pitch_reverse = pitch_reverse, roll_reverse=roll_reverse) # Calculate FPS. rtime = time.ticks_ms() utime = rtime-ltime total_uesd_time += utime total_fps += 1 print(f"used time:{utime}ms, fps:{round(1000/(utime),2)}, avg_fps:{round(total_fps*1000/total_uesd_time, 2)}") 找出这段代码中哪些是确定坐标的
最新发布
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值