题意:对一串数字进行抑或某数,和某数,或某数,统计某区间和的操作。

思路:因为化成二进制就4位可以建4颗线段树,每颗代表一位二进制。

and 如果该为是1  直接无视,是0则成段赋值为0;

or  如果是0 无视,是1则成段赋值为1;

xor 成段亦或,1个数和0个数交换;

sum 求和;

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include <iostream>
#define N 1000050
#define debug(x) printf(#x"= %d\n",x);
using namespace std;
int sum[][N * ], flag[][N * ], Xor[][N * ];
int a[N];
void pushup(int i, int now) {
sum[now][i] = sum[now][i << ] + sum[now][i << | ];
}
void pushdown(int i, int now, int l, int r) { int mid = (l + r) >> ;
if (flag[now][i] != -) {
flag[now][i << ] = flag[now][i << | ] = flag[now][i];
sum[now][i << ] = (mid - l + ) * flag[now][i];
sum[now][i << | ] = (r - mid) * flag[now][i];
Xor[now][i << ] = Xor[now][i << | ] = ;
flag[now][i] = -;
}
if (Xor[now][i]) {
Xor[now][i << ] ^= ;
sum[now][i << ] = (mid - l + ) - sum[now][i << ];
Xor[now][i << | ] ^= ;
sum[now][i << | ] = (r - mid) - sum[now][i << | ];
Xor[now][i] = ;
}
}
void build(int l, int r, int i, int now) { flag[now][i] = -;
Xor[now][i] = ;
if (l == r) {
sum[now][i] = ((a[l] >> now) & );
return;
}
int mid = (l + r) >> ;
build(l, mid, i << , now);
build(mid + , r, i << | , now);
pushup(i, now);
}
void update(int l, int r, int pl, int pr, int type, int va, int i, int now) {
if (l >= pl && r <= pr) {
if (type == ) {
sum[now][i] = (r - l + ) * va;
flag[now][i] = va;
Xor[now][i] = ;
} else {
sum[now][i] = (r - l + - sum[now][i]);
Xor[now][i] ^= ;
}
return;
}
pushdown(i, now, l, r);
int mid = (l + r) >> ;
if (pl <= mid)
update(l, mid, pl, pr, type, va, i << , now);
if (pr > mid)
update(mid + , r, pl, pr, type, va, i << | , now);
pushup(i, now);
} int query(int l, int r, int pl, int pr, int i, int now) {
if (l >= pl && r <= pr) {
return sum[now][i];
}
pushdown(i, now, l, r);
int mid = (l + r) >> ;
int tmp = ;
if (pl <= mid)
tmp += query(l, mid, pl, pr, i << , now);
if (pr > mid)
tmp += query(mid + , r, pl, pr, i << | , now);
pushup(i, now);
return tmp;
}
int main() {
int n, m, tt;
scanf("%d", &tt);
while (tt--) {
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i)
scanf("%d", &a[i]);
for (int i = ; i < ; ++i)
build(, n, , i);
while (m--) {
char s[];
scanf(" %s", s);
if (strcmp(s, "OR") == ) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
y++;
z++;
for (int i = ; i < ; ++i) {
if ((x >> i) & ) {
update(, n, y, z, , , , i);
}
}
} else if (strcmp(s, "AND") == ) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
y++;
z++;
for (int i = ; i < ; ++i) {
if (((x >> i) & ) == ) {
update(, n, y, z, , , , i);
}
}
} else if (strcmp(s, "XOR") == ) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
y++;
z++;
for (int i = ; i < ; ++i) {
if (((x >> i) & )) {
update(, n, y, z, , , , i);
}
}
} else {
int x, y;
scanf("%d%d", &x, &y);
x++;
y++;
int ans=;
for (int i = ; i < ; ++i) {
ans+=query(,n,x,y,,i)*(<<i);
// debug(ans);
}
printf("%d\n",ans);
}
}
}
return ;
}

FOJ 2105 Digits Count的更多相关文章

  1. ACM: FZU 2105 Digits Count - 位运算的线段树【黑科技福利】

     FZU 2105  Digits Count Time Limit:10000MS     Memory Limit:262144KB     64bit IO Format:%I64d & ...

  2. FZU 2105 Digits Count(线段树)

    Problem 2105 Digits Count Accept: 302 Submit: 1477 Time Limit: 10000 mSec Memory Limit : 262144 KB P ...

  3. FZU 2105 Digits Count

     Problem 2105 Digits Count Accept: 444    Submit: 2139 Time Limit: 10000 mSec    Memory Limit : 2621 ...

  4. FZU 2105 Digits Count(位数计算)

    Description 题目描述 Given N integers A={A[0],A[1],...,A[N-1]}. Here we have some operations: Operation ...

  5. fzu 2105 Digits Count ( 线段树 ) from 第三届福建省大学生程序设计竞赛

    http://acm.fzu.edu.cn/problem.php?pid=2105 Problem Description Given N integers A={A[0],A[1],...,A[N ...

  6. FZU 2105 Digits Count(按位维护线段树)

    [题目链接] http://acm.fzu.edu.cn/problem.php?pid=2105 [题目大意] 给出一个序列,数字均小于16,为正数,每次区间操作可以使得 1. [l,r]区间and ...

  7. FZU Problem 2105 Digits Count

    Problem Description Given N integers A={A[0],A[1],...,A[N-1]}. Here we have some operations: Operati ...

  8. FZU-2105 Digits Count (两种标记成段更新)

    题目大意:给n个0~15之间的数,有3种更新操作,1种询问操作.3种更新操作是:1.让某个闭区间的所有数字与一个0~15之间的数字进行逻辑与运算:2.让某个闭区间的所有数字与一个0~15之间的数字进行 ...

  9. FZU2105 Digits Count(按位建线段树)题解

    题意: 给出区间与.或.异或\(x\)操作,还有询问区间和. 思路: 因为数比较小,我们给每一位建线段树,这样每次只要更新对应位的答案. 与\(0\)和或\(1\)相当于重置区间,异或\(1\)相当于 ...

随机推荐

  1. 11 半联结 & 反联结

    半联结 和 反联结是 oracle 优化器能够选择用来在获取信息时应用的两个密切相关的联结方法(实际上是联结方法的选项) 半联结 IN 的半联结 select /* using in */ depar ...

  2. create table xxx as select 与 create table xxx like

    create table xxx )       | NO   | PRI | NULL    | auto_increment | | Name       | varchar() | NO   | ...

  3. (十一)C语言中内存堆和栈的区别

    在计算机领域,堆栈是一个不容忽视的概念,我们编写的C语言程序基本上都要用到.但对于很多的初学着来说,堆栈是一个很模糊的概念. 堆栈:一种数据结构.一个在程序运行时用于存放的地方,这可能是很多初学者的认 ...

  4. Oracle查看表结构的几种方法

    1,DESCRIBE 命令 使用方法如下: SQL> describe nchar_tst(nchar_tst为表名) 显示的结果如下:  名称                         ...

  5. 转:Teach Yourself Programming in Ten Years——用十年教会自己编程

    转自:http://blog.csdn.net/UndeadWraith/article/details/6140455 作者:Peter Norvig 译者:刘海粟 本文原文为:http://nor ...

  6. java按值传递相关理解

    Java没有引用传递只有按值传递,没有引用传递只有按值传递,值传递. 1. public class Test {     public static void main(String[] args ...

  7. Bootstrap列表

    一.HTML的列表 在HTML文档中,列表结构主要有三种:有序列表.无序列表和定义列表.具体使用的标签说明如下: 1.无序列表 <ul> <li>…</li> &l ...

  8. SDL2.0的SDL_Event事件处理

    SDL_Event事件集合 SDL_AudioDeviceEvent SDL_ControllerAxisEvent SDL_ControllerButtonEvent SDL_ControllerD ...

  9. CSS3的颜色透明度 ajax请求时loading

    1.background-color:rgba(0,0,0,0.65)         这行代码让覆盖层变黑色,且有0.6的透明度 正常情况下遮盖层会把透明度遗传给弹出框(它的子元素),但是利用CSS ...

  10. 任性,新建对象不用new

    先看最简单的一个例子: window.meng = window.meng || {}; (function () { /** * * @param {Number}width * @param {N ...