Range Minimum Queries

来源:互联网 发布:淘宝买的催情药管用吗 编辑:程序博客网 时间:2024/06/08 06:55

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 51 5 2 3 40 2 51 1 5 60 2 21 2 5 30 1 3Output:240
中文题意请看这里:

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;}






原创粉丝点击