【线段树】 FZU 2105 Digits Count

来源:互联网 发布:求职app 知乎 编辑:程序博客网 时间:2024/05/22 11:45

用线段树记录区间的二进制每一位1的个数。。。然后&操作就是在对应区间全部更新为0,|操作就是在对应区间全部更新为1.。。。^操作就是在对应区间翻转就行了。。。

#include <iostream>  #include <queue>  #include <stack>  #include <map>  #include <set>  #include <bitset>  #include <cstdio>  #include <algorithm>  #include <cstring>  #include <climits>  #include <cstdlib>#include <cmath>#include <time.h>#define maxn 1000005#define maxm 100005#define eps 1e-10#define mod 3#define INF 1e17#define lowbit(x) (x&(-x))  #define ls o<<1#define rs o<<1 | 1#define lson o<<1, L, mid  #define rson o<<1 | 1, mid+1, R  typedef long long LL;//typedef int LL;using namespace std;int num[maxn];int cnt[5][maxn<<2];int lazy[5][maxn<<2];int mark[5][maxn<<2];char s[100];int n, m, ql, qr, v, kk;void init(void){memset(mark, 0, sizeof mark);memset(lazy, -1, sizeof lazy);}void read(void){scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++)scanf("%d", &num[i]);}void pushup(int o){for(int i = 0; i < 5; i++)cnt[i][o] = cnt[i][ls] + cnt[i][rs];}void pushdown(int o, int L, int R){int mid = (L+R)>>1;for(int i = 0; i < 5; i++) {if(~lazy[i][o]) {cnt[i][ls] = (mid-L+1)*lazy[i][o];cnt[i][rs] = (R-mid)*lazy[i][o];lazy[i][ls] = lazy[i][rs] = lazy[i][o];mark[i][ls] = mark[i][rs] = 0;lazy[i][o] = -1;}if(mark[i][o]) {cnt[i][ls] = mid-L+1-cnt[i][ls];cnt[i][rs] = R-mid-cnt[i][rs];mark[i][ls] ^= 1;mark[i][rs] ^= 1;mark[i][o] = 0;}}}void build(int o, int L, int R){if(L == R) {for(int i = 0; i < 5; i++)cnt[i][o] = (num[L] & (1<<i)) == 0 ? 0 : 1;return;}int mid = (L+R)>>1;build(lson);build(rson);pushup(o);}void updata(int o, int L, int R){if(ql <= L && qr >= R) {if(kk == 0)for(int i = 0; i < 5; i++)if((1<<i) & v) {cnt[i][o] = R-L+1-cnt[i][o];mark[i][o] ^= 1;}if(kk == 1)for(int i = 0; i < 5; i++)if((1<<i) & v) {cnt[i][o] = R-L+1;lazy[i][o] = 1;mark[i][o] = 0;}if(kk == 2)for(int i = 0; i < 5; i++)if(!((1<<i) &v)) {cnt[i][o] = 0;lazy[i][o] = 0;mark[i][o] = 0;}return;}pushdown(o, L, R);int mid = (L+R)>>1;if(ql <= mid) updata(lson);if(qr > mid) updata(rson);pushup(o);}int query(int o, int L, int R){if(ql <= L && qr >= R) {int ans = 0;for(int i = 0; i < 5; i++)ans += (1<<i)*cnt[i][o];return ans;}pushdown(o, L, R);int mid = (L+R)>>1, ans = 0;if(ql <= mid) ans += query(lson);if(qr > mid) ans += query(rson);pushup(o);return ans;}void work(void){while(m--) {scanf("%s", s);if(s[0] == 'S') {scanf("%d%d", &ql, &qr);ql++, qr++;printf("%d\n", query(1, 1, n));}else {scanf("%d%d%d", &v, &ql, &qr);ql++, qr++;if(s[0] == 'X') kk = 0;if(s[0] == 'O') kk = 1;if(s[0] == 'A') kk = 2;updata(1, 1, n);}}}int main(void){int _;while(scanf("%d", &_)!=EOF) {while(_--) {init();read();build(1, 1, n);work();}}return 0;}


0 0