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 ≤ Ai, X ≤ 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;
}