zoukankan      html  css  js  c++  java
  • 牛客练习赛 29 E 位运算?位运算!(线段树)

    题目链接  牛客练习赛29E

    对$20$位分别建立线段树。首先$1$和$2$可以合起来搞(左移右移其实是等效的)

    用个lazy标记下。转移的时候加个中间变量。

    $3$和$4$其实就是区间$01$覆盖操作。

    $5$就直接做就可以了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    
    typedef long long LL;
    
    const int N = 2e5 + 10;
    
    int s[N << 2][21], tmp[21], lazy[N << 2];
    int a[N];
    int n, q;
    int op, l, r, v;
    LL  ans;
    
    void rotate(int x, int v){
    	rep(i, 0, 19) tmp[i] = s[x][(i + v) % 20];
    	rep(i, 0, 19) s[x][i] = tmp[i];
    	lazy[x] += v;
    	lazy[x] %= 20;
    }
    
    
    void build(int x, int l, int r){
    	if (l == r){
    		rep(i, 0, 19) s[x][i] = (a[l] >> i) & 1;
    		return;
    	}
    
    	int mid = (l + r) >> 1;
    	build(x << 1, l, mid);
    	build(x << 1 | 1, mid + 1, r);
    	rep(i, 0, 19) s[x][i] = s[x << 1][i] + s[x << 1 | 1][i];
    }
    
    void update(int x, int L, int R){
    	if (l <= L && R <= r){
    		if (op == 1) rotate(x, v);
    		else if (op == 2) rotate(x, 20 - v);
    		else if (op == 3){
    			rep(i, 0, 19) if ((v >> i) & 1) s[x][i] = R - L + 1;
    		}
    
    		else if (op == 4){
    			rep(i, 0, 19) if (!((v >> i) & 1)) s[x][i] = 0;
    		}
    
    		else{
    			rep(i, 0, 19) ans += ((LL)s[x][i] << i);
    		}
    
    		return ;
    	}
    
    	int len = R - L + 1, mid = (L + R) >> 1;
    
    	if (lazy[x]){
    		rotate(x << 1, lazy[x]);
    		rotate(x << 1 | 1, lazy[x]);
    		lazy[x] = 0;
    	}
    
    	rep(i, 0, 19){
    		if (s[x][i] == len){
    			s[x << 1][i] = len - len / 2;
    			s[x << 1 | 1][i] = len / 2;
    		}
    
    		else if (s[x][i] == 0){
    			s[x << 1][i] = 0;
    			s[x << 1 | 1][i] = 0;
    		}
    
    	}
    
    	if (l <= mid) update(x << 1, L, mid);
    	if (r  > mid) update(x << 1 | 1, mid + 1, R);
    	rep(i, 0, 19) s[x][i] = s[x << 1][i] + s[x << 1 | 1][i];
    }
    			
    		
    
    
    int main(){
    
    	scanf("%d%d", &n, &q);
    
    	rep(i, 1, n) scanf("%d", a + i);
    	build(1, 1, n);
    
    	while (q--){
    		scanf("%d%d%d%d", &op, &l, &r, &v);	
    		ans = 0;
    		update(1, 1, n);
    		if (op == 5) printf("%lld
    ", ans);
    	}
    
    	return 0;
    }
    

      

  • 相关阅读:
    【EmguCv】人脸/人眼检测
    iOS 9下Universal Link(通用链接)开发
    【JavaWeb】SpringMvc返回json
    【nlp】湖北师范大学贴吧帖子标题词频统计
    【C#】EAN-13条形码生成与识别
    【C#】身份证识别(三):身份证信息识别
    【C#】身份证识别(二):提取目标区域图像
    米勒罗宾素性测试算法简介+模板(转)
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/9821671.html
Copyright © 2011-2022 走看看