Description

题目描述

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

Operation 1: AND opn L R

Here opn, L and R are integers.

For L≤i≤R, we do A[i]=A[i] AND opn (here "AND" is bitwise operation).

Operation 2: OR opn L R

Here opn, L and R are integers.

For L≤i≤R, we do A[i]=A[i] OR opn (here "OR" is bitwise operation).

Operation 3: XOR opn L R

Here opn, L and R are integers.

For L≤i≤R, we do A[i]=A[i] XOR opn (here "XOR" is bitwise operation).

Operation 4: SUM L R

We want to know the result of A[L]+A[L+1]+...+A[R].

Now can you solve this easy problem?

给定N个整数A={A[0],A[1],...,A[N-1]}。下面有一些操作。

操作1:AND opn L R

其中opn,L和R都是整数。

对于L≤i≤R,我们使A[i]=A[i] AND opn(这里的"AND"是位运算)。

操作2:OR opn L R

其中opn,L和R都是整数。

对于L≤i≤R,我们使A[i]=A[i] OR opn(这里的"OR"是位运算)。

操作3:XOR opn L R

其中opn,L和R都是整数。

对于L≤i≤R,我们使A[i]=A[i] XOR opn(这里的"XOR"是位运算)。

操作4:SUM L R

我们想要知道A[L]+A[L+1]+...+A[R]的值。

现在,你能解决这个简单的问题吗?

Input

输入

The first line of the input contains an integer T, indicating the number of test cases. (T≤100)

Then T cases, for any case, the first line has two integers n and m (1≤n≤1,000,000, 1≤m≤100,000), indicating the number of elements in A and the number of operations.

Then one line follows n integers A[0], A[1], ..., A[n-1] (0≤A[i]<16,0≤i<n).

Then m lines, each line must be one of the 4 operations above. (0≤opn≤15)

第一行有一个整数T,表示测试样例的数量。(T≤100)

后面有T个样例,每个样例的第一行有2个整数n和m(1≤n≤1,000,000, 1≤m≤100,000),表示元素数量与操作次数。

下一行有n个整数A[0], A[1], ..., A[n-1] (0≤A[i]<16,0≤i<n)。

接着m行,每行都是上述4种操作的其中一个。(0≤opn≤15)

Output

输出

For each test case and for each "SUM" operation, please output the result with a single line.

对于每个测试样例的每个"SUM"操作,都要输出到单独的一行。

Sample Input - 输入样例

Sample Output - 输出样例

1

4 4

1 2 4 7

SUM 0 2

XOR 5 0 0

OR 6 0 3

SUM 0 2

7

18

【题解】

  单纯的线段树。

  利用线段树查找快速的特点保存元素,对于某段区间内相同状态的元素进行合并。

  进行操作的时候不断查找,直到可操作的区间。因为数据都是非负整数,所以可以用负数标记元素不同的区间。

  PS:状态发生变化的时候都要下压,注意深入的方向。

  PS2:简单的运算速度是高于开辟空间的速度,所以没必要把线段树每个节点的左右区间都记录下来。

  PSP:开辟元素数量4倍的空间一定够用。

【代码 C++】

 #include<cstdio>
int data[ << ], opn, L, R;
char ts[];
int build(int data_i, int L, int R){//[L, R]
if (L == R) scanf("%d", &data[data_i]);
else{
int mid = (L + R) >> ;// [L, mid] (mid, R]
L = build(data_i << | , L, mid);
R = build(data_i + << , mid + , R);
if (L == R) data[data_i] = L;
else data[data_i] = -;
}
return data[data_i];
}
int bitwise_peration(int data_i, int L_now, int R_now){
if (data[data_i] != - && L <= L_now && R_now <= R){
if (*ts == 'A') data[data_i] &= opn;
else if (*ts == 'O') data[data_i] |= opn;
else if (*ts == 'X') data[data_i] ^= opn;
}
else{
if (data[data_i] != -) data[data_i << | ] = data[data_i + << ] = data[data_i];
int mid = (R_now + L_now) >> ;
if (R <= mid){// goto Right
L_now = bitwise_peration(data_i << | , L_now, mid);
R_now = data[data_i + << ];
}
else if (mid < L){// goto Left
L_now = data[data_i << | ];
R_now = bitwise_peration(data_i + << , mid + , R_now);
}
else{
L_now = bitwise_peration(data_i << | , L_now, mid);
R_now = bitwise_peration(data_i + << , mid + , R_now);
}
if (L_now == R_now) data[data_i] = L_now;
else data[data_i] = -;
}
return data[data_i];
}
int sum(int data_i, int L_now, int R_now){
if (data[data_i] != - && L <= L_now && R_now <= R){
return data[data_i] * (R_now - L_now + );
}
if (data[data_i] != -) data[data_i << | ] = data[data_i + << ] = data[data_i];
int mid = (R_now + L_now) >> ;
if (R <= mid) return sum(data_i << | , L_now, mid);
if (mid < L) return sum(data_i + << , mid + , R_now);
return sum(data_i << | , L_now, mid) + sum(data_i + << , mid + , R_now);
}
int main(){
int t, m, n, i;
for (scanf("%d", &t); t; --t){
scanf("%d%d", &n, &m);
--n;
build(, , n);
while (m--){
scanf("%s", ts);
if (*ts == 'S'){
scanf("%d%d", &L, &R);
printf("%d\n", sum(, , n));
}
else{
scanf("%d%d%d", &opn, &L, &R);
bitwise_peration(, , n);
}
}
}
return ;
}
 #include<cstdio>
int L, R;
char data[], opn, ts[];
int read_g(){// 输入挂
int add = getchar() - '';
int a = getchar();
while (a >= '' && a <= '') add = add * + a - '', a = getchar();
return add;
}
int build(int data_i, int L, int R){// [L, R]
if (L == R) data[data_i] = read_g();
else{// [L, mid] (mid, R]
int mid = (L + R) >> ;
L = build(data_i << | , L, mid);
R = build(data_i + << , ++mid, R);
if (L == R) data[data_i] = L;
else data[data_i] = -;
}
return data[data_i];
}
int bitwise_peration(int data_i, int L_now, int R_now){
if (~data[data_i] && L <= L_now && R_now <= R){
if (*ts == 'A') data[data_i] &= opn;
else if (*ts == 'O') data[data_i] |= opn;
else if (*ts == 'X') data[data_i] ^= opn;
}
else{
if (~data[data_i]) data[data_i << | ] = data[data_i + << ] = data[data_i];
int mid = (R_now + L_now) >> ;
if (R <= mid){// goto Right
L_now = bitwise_peration(data_i << | , L_now, mid);
R_now = data[data_i + << ];
}
else if (mid < L){// goto Left
L_now = data[data_i << | ];
R_now = bitwise_peration(data_i + << , mid + , R_now);
}
else{
L_now = bitwise_peration(data_i << | , L_now, mid);
R_now = bitwise_peration(data_i + << , mid + , R_now);
}
if (L_now == R_now) data[data_i] = L_now;
else data[data_i] = -;
}
return data[data_i];
}
int sum(int data_i, int L_now, int R_now){
if (~data[data_i]){
if (L_now < L) L_now = L;
if (R < R_now) R_now = R;
return data[data_i] * (++R_now - L_now);
}
int mid = (R_now + L_now) >> ;
if (R <= mid) return sum(data_i << | , L_now, mid);
if (mid < L) return sum(++data_i << , ++mid, R_now);
return sum(data_i << | , L_now, mid) + sum(data_i + << , mid + , R_now);
}
int main(){
int m, n;
short t = read_g();
while (t--){
n = read_g(); m = read_g(); --n;
build(, , n);
while (m--){
scanf("%s", ts); getchar();
if (*ts == 'S'){
L = read_g(); R = read_g();
printf("%d\n", sum(, , n));
}
else{
opn = read_g(); L = read_g(); R = read_g();
bitwise_peration(, , n);
}
}
}
return ;
}

FZU 2105

FZU 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 ( 线段树 ) from 第三届福建省大学生程序设计竞赛

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

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

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

  6. FZU Problem 2105 Digits Count

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

  7. FOJ 2105 Digits Count

    题意:对一串数字进行抑或某数,和某数,或某数,统计某区间和的操作. 思路:因为化成二进制就4位可以建4颗线段树,每颗代表一位二进制. and 如果该为是1  直接无视,是0则成段赋值为0: or  如 ...

  8. FZU 2105 (线段树)

     Problem 2105 Digits Count  Problem Description Given N integers A={A[0],A[1],...,A[N-1]}. Here we h ...

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

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

随机推荐

  1. (顺序表的应用5.4.2)POJ 1591 M*A*S*H(约瑟夫环问题的变形——变换步长值)

    /* * POJ_1591_2.cpp * * Created on: 2013年10月31日 * Author: Administrator */ #include <iostream> ...

  2. android 项目学习随笔一(闪屏 )

    1.取标题栏且全屏 <activity android:name="com.ecollab.zhsh66.SplashActivity" android:label=&quo ...

  3. Centos7 安装配置NFS

    一.安装 NFS 服务器所需的软件包 # yum install -y nfs-utils 二.编辑exports文件 # vim /etc/exports /data/disk1/video *(a ...

  4. 如何为github上的项目添加gif效果图

    一.制作gif图片 如何制作可以参考: http://www.jianshu.com/p/27ec6375b8ab?utm_campaign=maleskine&utm_content=not ...

  5. sql必知必会(第四版) 学习笔记

    还有一个<Sqlserver2008技术内幕>的笔记,也很好!~ http://www.cnblogs.com/liupeng61624/p/4354983.html 温习一遍简单的sql ...

  6. 更改printk打印级别

    1.查看当前控制台的打印级别 cat /proc/sys/kernel/printk 4    4    1    7 其中第一个"4"表示内核打印函数printk的打印级别,只有 ...

  7. c# 服务端

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  8. WCF自定义地址路由映射(不用svc文件)

    一般在创建WCF服务时会用Serivce.svc文件访问,地址如:http://localhost/applicationname/Serivce.svc/Name 现在用路由映射成:http://l ...

  9. Winsock系列函数 及 Socket通信流程

    Socket是一种网络通信机制   Winsock系列函数   1. Socket 创建socket   2. Connect 尝试连接远端Socket   3. Send 在某个Socket 向远端 ...

  10. HashMap, HashTable, CurrentHashMap的区别

    转载:http://www.jianshu.com/p/c00308c32de4 HashMap vs ConcurrentHashMap 引入ConcurrentHashMap是为了在同步集合Has ...