bzoj5312: 冒险(势能均摊线段树)

题目链接

BZOJ5312: 冒险

题解

如果一次操作对区间& 和 区间| 产生的影响是相同的,那么该操作对整个区间的影响都是相同的
对于每次操作,在某些位上的值,对于整个区间影响是相同的,对相同影响的操作直接打标记
否则递归子树
复杂度证明:
https://csacademy.com/contest/round-70/task/and-or-max/solution/

代码

#include<cstdio> 
#include<algorithm> 
inline int read() { 
	int x = 0,f = 1; 
	char c = getchar(); 
	while(c < '0' || c > '9'){if(c == '-')f = -1; c = getchar(); } 
	while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); 
	return x *f ; 
} const int maxn = 2000007; 
int n,a[maxn],m; 
int A[maxn << 1],O[maxn << 1],t[maxn << 1],tag[maxn]; 
#define ls x << 1 
#define rs x << 1 | 1
inline void update(int x) { 
 	A[x] = A[ls] & A[rs];
    O[x] = O[ls] | O[rs];
	t[x] = std::max(t[ls],t[rs]); 
} 
inline void ps(int x,int k ) { tag[x] += k; A[x] += k; O[x] += k; t[x] += k;	}  
void pushdown(int x) { 
	ps(ls,tag[x]); 
	ps(rs,tag[x]); 
	tag[x] = 0; 
	return; 
} 
void build(int x,int l,int r) { 
	if(l == r) { 
		A[x] = O[x] = t[x] = a[l]; 
		return ; 
	}	 
	int mid = l + r >> 1; 
	build(x << 1,l,mid); build(x << 1 | 1,mid + 1,r); 
	update(x); 
} 
void modify(int x,int l,int r,int L,int R,int k,int type) { 
	bool t = false;   
	if(type == 1) {  
		if((O[x] & k) == O[x]) return; 
		t = ((A[x] & k) - A[x] == (O[x] & k) - O[x]); 
	} else { 
		if((A[x] | k) == A[x]) return; 
		t = ((A[x] | k) - A[x] == (O[x] | k) - O[x]); 
	} 
	if(l >= L && r <= R && t) { 
        if(type == 1) ps(x,(A[x] & k) - A[x]); 
		else ps(x, (O[x] | k) - O[x]); 
		return; 
	} 
	if(tag[x]) pushdown(x); 
	int mid = l + r >> 1; 
	if(L <= mid) modify(ls,l,mid,L,R,k,type); 
	if(R > mid) modify(rs,mid + 1,r,L,R,k,type); 
	update(x); 
} 
int query(int x,int l,int r,int L ,int R) { 
	if(l >= L && r <= R) return t[x]; 
	int ret = 0; 
	if(tag[x]) pushdown(x); 
	int mid = l + r >> 1; 
	if(L <= mid) ret = std::max(ret,query(ls,l,mid,L,R)); 
	if(R >  mid) ret = std::max(ret,query(rs,mid + 1,r,L,R)); 
	return ret;  
} 
int main() { 
	n = read(); m = read(); 
	for(int i = 1;i <= n;++ i) a[i] = read(); 
	build(1,1,n); 
	for(int i = 1;i <= m;i += 1) { 
		int type = read(),l = read(),r = read(); 
		if(type == 1) { 
			int x = read(); 
			modify(1,1,n,l,r,x,type); 
		} else if(type == 2) { 
			int x = read(); 
			modify(1,1,n,l,r,x,type); 
		} else 
			printf("%d
",query(1,1,n,l,r)); 
	} 
	return 0; 
} 
原文地址:https://www.cnblogs.com/sssy/p/9645178.html