AND RMQ线段树

 

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false) 
#define endl '\n'
using namespace std;
const int N = 4e5 + 10;
int n, m;
int a[N];
struct node
{
	int l, r;
	int sum;//这个是在当前区间每个数的或 
	int maxx;//当前区间的最大值 
} tree[N << 2];

inline void pushup(int p)
{
	tree[p].maxx = max(tree[p << 1].maxx, tree[p << 1 | 1].maxx);
	tree[p].sum = tree[p << 1].sum | tree[p << 1 | 1].sum;//中间的竖就是或 
	return ;
}

void build(int p, int l, int r)
{
	tree[p].l = l, tree[p].r = r;
	if (l == r)
	{
		tree[p].sum = a[l];
		tree[p].maxx = a[l];
		return ;
	} 
	int mid = (l + r) >> 1;
	build(p << 1, l, mid);
	build(p << 1 | 1, mid + 1, r);
//	pushup(p);
	tree[p].maxx = max(tree[p << 1].maxx, tree[p << 1 | 1].maxx);
	tree[p].sum = tree[p << 1].sum | tree[p << 1 | 1].sum;//中间的竖就是或 
	
}

void update1(int p, int l, int r, int value)
{
	if (tree[p].l > r || tree[p].r < l)
		return ;
	if (tree[p].l == tree[p].r)
	{
		tree[p].sum = tree[p].maxx & value;
		tree[p].maxx = tree[p].maxx & value;
		return ;
	}
	//这一步就是题解的亮点,所有的数的|所得的数,&其中任何一个数还是等于他自己,
	//所以如果value & sum 还是 == sum, 那么value就相当与sum的作用,因为那些1没变 
	if ((tree[p].sum & value) == tree[p].sum)
		return ;
	update1(p << 1, l, r, value);
	update1(p << 1 | 1, l, r, value);
	pushup(p);
}

void update2(int p, int idx, int value)
{
	if (tree[p].l > idx || tree[p].r < idx)//不满足区间要求的直接return 
		return ;
	if (tree[p].l == tree[p].r && tree[p].l == idx)
	{
		tree[p].sum = value;
		tree[p].maxx = value;
		return ;
	}	
	update2(p << 1, idx, value);
	update2(p << 1 | 1, idx, value);
	pushup(p);
}

int query(int p, int l, int r)
{
	if (tree[p].l > r || tree[p].r < l)//不满足区间要求的直接return,这样剩下的点全在l,r里,所以有下面的l==r直接可以return 
		return -1;
	if (l <= tree[p].l && tree[p].r <= r)
	{
		return tree[p].maxx;
	}	
	//不断的往下执行,
	//-1 和 -1 比较 
	//1. -1 和 一个tree[p].maxx比较
	//2. 一个tree[p].maxx和另一个tree[p].maxx比较
	//所以直接取max 
	return max(query(p << 1, l, r), query(p << 1 | 1, l, r));
}


int main()
{
	IOS; cin.tie(0), cout.tie(0);
	cin >> n >> m;
	
	for (int i = 1; i <= n; ++i)
	{
		cin >> a[i];
	}
	
	build(1, 1, n);
	
	for (int i = 1; i <= m; ++i)
	{	
		string op;
		cin >> op;
		if (op[0] == 'A')
		{
			int l, r, v;
			cin >> l >> r >> v;
			update1(1, l, r, v);
		}
		else if (op[0] == 'U')
		{
			int x, v;
			cin >> x >> v;
			update2(1, x, v);
		}
		else if (op[0] == 'Q')
		{
			int l, r;
			cin >> l >> r;
			int maxx = query(1, l, r);
			cout << maxx << endl;
		}
	}
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值