zoukankan      html  css  js  c++  java
  • 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; 
    } 
    
  • 相关阅读:
    [BestCoder Round #3] hdu 4907 Task schedule (模拟简单题)
    .NET中的PublicKeyToken以及强命名问题
    bug统计分析续(一)基于SQL的Bug统计方法
    iOS项目开发实战——通过Http Get方式与server通信
    TCP与UDP的区别(转)
    Telit GPRS模块测试报告
    GPRS优点介绍及GPRS上网相关知识(转)
    MC34063中文资料及应用实例(转)
    MC34063+MOSFET扩流 12V-5V 折腾出了高效率电路(转)
    Bluez SPP实现代码分析(转)
  • 原文地址:https://www.cnblogs.com/sssy/p/9645178.html
Copyright © 2011-2022 走看看