列表

详情


NC19837. 位运算?位运算!

描述

请实现一个数据结构支持以下操作:
区间循环左右移,区间与,区间或,区间求和。

输入描述

第一行n,q表示数列长度及操作次数。
第二行n个数表示初始序列。
接下来q行表示操作。
操作格式如下:
一行表示一个操作。所有操作形如 opt l r v。
opt=1 表示将区间[l,r]循环右移v位。
opt=2 表示将区间[l,r]循环左移v位。
opt=3 表示将区间[l,r]按位或上v。
opt=4 表示将区间[l,r]按位与上v。
opt=5 询问区间[l,r]的和。
保证opt=1或2时 1 ≤ v ≤ 20
注意:为了优化你的做题体验,操作5也会输入一个v,但是是没有意义的。
注意:循环左右移在20个二进制位的意义下进行

输出描述

对于每个opt=5的操作,输出一个数表示答案。

示例1

输入:

10 10
10112 23536 1305 7072 12730 29518 12315 3459 12435 29055
4 5 10 12373
2 1 6 7
5 4 10 24895
1 1 4 8
5 3 7 7767
5 7 9 6127
4 2 8 30971
5 4 10 2663
1 7 10 1
1 2 9 5

输出:

2001530
1600111
24611
49482

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1707ms, 内存消耗: 45384K, 提交时间: 2019-10-27 16:54:25

#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(){
 	//freopen("in.txt","r",stdin);
    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\n", ans);
        /*for (int i=1; i<=n; i++){
        	l=i,r=i,op=5;
        	update(1,1,n);
        	printf ("...%lld%c",ans,i==n?'\n':' ');
		}*/
    }
 
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 1357ms, 内存消耗: 45152K, 提交时间: 2018-10-20 14:28:35

#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\n", ans);
	}

	return 0;
}


上一题