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

思路:因为化成二进制就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. Java数组实现五子棋功能

    package ch4; import java.io.*; /** * Created by Jiqing on 2016/11/9. */ public class Gobang { // 定义棋 ...

  2. RedHat 7配置yum源

    卸载自带的yum软件包 rpm -e yum-utils--.el7.noarch --nodeps rpm -e yum-rhn-plugin--.el7.noarch --nodeps rpm - ...

  3. HTML5Canvas标签

     

  4. 2年后的Delphi XE6

    1.有幸下载到Delphi XE6,下载地址如下: http://altd.embarcadero.com/download/radstudio/xe6/delphicbuilder_xe6_win. ...

  5. a链接onclick="window.location.href=在ie6上面无法执行解决

    <a href="javascript:void(0)" onclick="window.location.href=document.getElementById ...

  6. C++——对象和类

    最重要的OOP特性: *抽象: *封装和数据隐藏: *多态: *继承: *代码的可重用性: 一.抽象和类 1.类型 指定基本类型完成了三项工作:1).决定数据对象需要的内存数量:2).决定如何解释内存 ...

  7. go语言中间的循环

    在Go语言中只有很少的几个控制结构,它没有while或者do-while循环. 但是它有for.switch.if.而且switch接受像for那样可选的初始化语句.下面来认识一下他们 一.if语句 ...

  8. scala调用java的方法,返回了一个对象链表List<Student>,在scala中遍历该链表获取指定Student的名字name

    假设Student类如下: class Student { private int no; private String name; public int getNo() { return no; } ...

  9. hiho_1070_RMQ

    题目 区间最小值查询,但是支持对数组中的任意数字进行修改. 分析 采用RMQ_ST算法的O(1)算法不支持修改,因为每次修改都要重新设置动归数组.因此采用线段树解决,修改和查询的复杂度均为O(logN ...

  10. ulua slua 下载地址

    ulua http://www.yanyulin.info/pages/2015/01/27193946190814.html   http://www.manew.com/blog-27966-25 ...