`
Simone_chou
  • 浏览: 195851 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

Digits Count(线段树)

    博客分类:
  • FZU
 
阅读更多

 

Problem 2105 Digits Count

Accept: 144    Submit: 865
Time Limit: 10000 mSec    Memory Limit : 262144 KB

 

Problem 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?

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)

Output

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

Sample Input

1
4 4
1 2 4 7
SUM 0 2
XOR 5 0 0
OR 6 0 3
SUM 0 2

Sample Output

7
18

Hint

A = [1 2 4 7]

SUM 0 2, result=1+2+4=7;

XOR 5 0 0, A=[4 2 4 7];

OR 6 0 3, A=[6 6 6 7];

SUM 0 2, result=6+6+6=18.

 

 

       题意:

       给出 T (1 ~ 100)组 case,每组 case 给出 N(1 ~ 1000000),M(1 ~ 100000),代表有 N 个数 ai(0 ~ 16),和 M 个操作。操作有 4 类:

       1、SUM A B 代表将 A 到 B 的数求和;

       2、XOR K A B 代表将 A 到 B 的数异或 K;

       3、OR K A B 代表将 A 到 B 的数或 K;

       4、AND K A B 代表将 A 到 B 的数与 K;

       输出所有 SUM 操作时候的结果。

 

       思路:

       线段树 + 区间操作。将每个数拆位后每位建线段树,数最大才 16 所以建 4 颗线段树即可。

       与 CF 那题不同的是多了 OR 和 AND 的操作,或 0 的结果是不改变原来状态的,或 1 的结果是所有的数都会变成 1;与 1 的结果是不改变原来的状态的,与 0 的结果是所有的数都会变成 0。那么可以开另外一个标记域标记区间是否被 0 或者 被 1 覆盖的情况,另外一个标记是异或的情况。

       异或标记和覆盖标记是不会同时存在的,oth 标记 -1 代表未被覆盖,0 代表被 0 覆盖,1 代表被 1 覆盖;xor 标记 1 代表相反一次状态,0 代表不改变状态。若这个标记域被 0 或者被 1 覆盖,当异或的时候直接改变覆盖标记即可,其他异或操作和 CF 那题一样。

 

       AC:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAX = 1000005;

int n, dim, L, R, res;
int num[MAX];
int tree[5][MAX * 3], flag_xor[5][MAX * 3], flag_oth[5][MAX * 3];

void Mark (int k, int l, int r) {
        int mid = (l + r) >> 1;
        if (flag_oth[dim][k] != -1) {
                tree[dim][k << 1] = (mid - l + 1) * flag_oth[dim][k];
                tree[dim][k << 1 | 1] = (r - mid) * flag_oth[dim][k];
                flag_oth[dim][k << 1] = flag_oth[dim][k << 1 | 1] = flag_oth[dim][k];
                flag_xor[dim][k << 1] = flag_xor[dim][k << 1 | 1] = 0;
                flag_oth[dim][k] = -1;
        }

        if (flag_xor[dim][k]) {
                flag_xor[dim][k] = 0;
                tree[dim][k << 1] = mid - l + 1 - tree[dim][k << 1];
                tree[dim][k << 1 | 1] = r - mid - tree[dim][k << 1 | 1];
                if (flag_oth[dim][k << 1] != -1) flag_oth[dim][k << 1] ^= 1;
                else flag_xor[dim][k << 1] ^= 1;
                if (flag_oth[dim][k << 1 | 1] != -1) flag_oth[dim][k << 1 | 1] ^= 1;
                else flag_xor[dim][k << 1 | 1] ^= 1;
        }

}

void Build (int k, int l, int r) {
        int mid = (l + r) >> 1;
        flag_oth[dim][k] = -1;
        flag_xor[dim][k] = 0;
        if (l == r) {
                tree[dim][k] = (num[l] >> dim) & 1;
                return;
        }
        Build(k << 1, l, mid);
        Build(k << 1 | 1, mid + 1, r);
        tree[dim][k] = tree[dim][k << 1] + tree[dim][k << 1 | 1];
}

void Sum (int k, int l, int r) {
        int mid = (l + r) >> 1;
        if (L > r || R < l) return;
        if (L <= l && R >= r) {
                res += tree[dim][k];
                return;
        }
        Mark(k, l, r);
        Sum(k << 1, l, mid);
        Sum(k << 1 | 1, mid + 1, r);
}

void Update (int op, int k, int l, int r) {
        int mid = (l + r) >> 1;
        if (L > r || R < l) return;
        if (L <= l && R >= r) {
                if (op == 1) {
                        tree[dim][k] = r - l + 1 - tree[dim][k];
                        if (flag_oth[dim][k] != -1) flag_oth[dim][k] ^= 1;
                        else flag_xor[dim][k] ^= 1;
                } else if (op == 2) {
                        tree[dim][k] = r - l + 1;
                        flag_xor[dim][k] = 0;
                        flag_oth[dim][k] = 1;
                } else if (op == 3) {
                        tree[dim][k] = 0;
                        flag_xor[dim][k] = 0;
                        flag_oth[dim][k] = 0;
                }
                return;
        }
        Mark(k, l ,r);
        Update(op, k << 1, l, mid);
        Update(op, k << 1 | 1, mid + 1, r);
        tree[dim][k] = tree[dim][k << 1 | 1] + tree[dim][k << 1];
}

int main() {
        int t;
        scanf("%d", &t);
        while (t--) {

                int m;
                scanf("%d%d", &n, &m);
                for (int i = 1; i <= n; ++i)
                        scanf("%d", &num[i]);

                for (dim = 0; dim < 4; ++dim)
                        Build(1, 1, n);

                while (m--) {
                        char s[10];
                        int ans;
                        scanf("%s", s);
                        if (s[0] == 'S') {
                                int sum = 0;
                                scanf("%d%d", &L, &R);
                                ++L, ++R;
                                for (dim = 0; dim < 4; ++dim) {
                                        res = 0;
                                        Sum(1, 1, n);
                                        sum += (res * (1 << dim));
                                }

                                printf("%d\n", sum);

                        } else if (s[0] == 'X') {
                                scanf("%d%d%d", &ans, &L, &R);
                                ++L, ++R;

                                for (dim = 0; dim < 4; ++dim) {
                                        if ((ans >> dim) & 1) Update(1, 1, 1, n);
                                }
                        } else if (s[0] == 'O') {
                                scanf("%d%d%d", &ans, &L, &R);
                                ++L, ++R;
                                for (dim = 0; dim < 4; ++dim) {
                                        if ((ans >> dim) & 1) Update(2, 1, 1, n);
                                }
                        } else if (s[0] == 'A') {
                                scanf("%d%d%d", &ans, &L, &R);
                                ++L, ++R;
                                for (dim = 0; dim < 4; ++dim)
                                        if (!((ans >> dim) & 1)) Update(3, 1, 1, n);
                        }
                }
        }
        return 0;
}
 

 

分享到:
评论

相关推荐

    Count the frequency distribution of units digits

    Count the frequency distribution of units digits

    NVIDIA DIGITS安装教程

    ### NVIDIA DIGITS 安装与使用教程 #### 一、NVIDIA DIGITS 概述 NVIDIA DIGITS 是一款专为深度学习设计的 Web 应用工具,它为用户提供了一个直观且易于使用的图形化界面来操作 Caffe。通过 DIGITS,用户可以在...

    WIndows下为Caffe安装NVIDIA DIGITS可视化工具.docx

    Windows 下为 Caffe 安装 NVIDIA DIGITS 可视化工具 本文档介绍了如何在 Windows 平台下安装 NVIDIA DIGITS 可视化工具,并与 Caffe 结合使用。DIGITS 是 NVIDIA 的深度学习开发平台,提供了图形化的界面来训练和...

    DIGITS 安装配置

    这个压缩包主要是我用Anaconda创建py27环境下安装DIGITS的过程,其中主要自己安装过程中的各种非常细节的踩坑和安装细节流程等。最后的安装配置都是OK的,不过最后由于我笔记本中的python图像处理库scikit-image的...

    pi_million_digits.txt

    pi_million_digits, python课程文件读取用,codeforge下载

    Add Digits

    一个给定的正整数,循环的将每一位相加,只要得到的结果是大于10的数,就继续循环相加

    Laravel开发-unique-digits

    在Laravel框架中,开发一个名为"unique-digits"的功能主要涉及到生成唯一数字序列的逻辑,这在诸如票号、订单号或者用户ID等场景下非常常见。Laravel提供了丰富的工具和功能,使得构建这样的系统变得高效且易于维护...

    Digits.rar

    《手写数字识别:探索与理解OpenCV中的Digits样本数据集》 在计算机视觉领域,手写数字识别是一项基础且重要的任务,广泛应用于自动柜员机(ATM)的读取、邮件分类以及各种数字化系统中。OpenCV,一个强大的开源...

    digits.rar

    标题中的“digits.rar”指的是一个压缩文件,通常用于存储多个相关文件或数据。在这个特定的上下文中,这个压缩包包含了与机器学习相关的资料,特别是针对手写数字识别系统的数据集。 手写数字识别系统是一种应用...

    THE MNIST DATABASE of handwritten digits

    The MNIST database of handwritten digits, available from this page, has a training set of 60,000 examples, and a test set of 10,000 examples. It is a subset of a larger set available from NIST. The ...

    digits修改截图.tar.gz

    这个是关于digits中解决Can't pickle &lt;class 'caffe.proto.caffe_pb2.NetParameter'&gt;: it's not the same object as caffe.proto.caffe_pb2.NetParameter问题的解决方法,我将需要修该的地方截图了,附带了一个原...

    digits.zip

    标题“digits.zip”所指的是一个包含手写数字识别数据集的压缩文件,它采用的是k-近邻(k-Nearest Neighbors, k-NN)算法。k-NN是一种非参数监督学习方法,广泛应用于分类任务,特别是图像识别领域。在这个特定的...

    knn_digits_KNN数字识别_knn_KNNdigits_training_passageda4_数字识别knn_

    总结来说,"KNN_digits_KNN数字识别"项目是利用KNN算法进行手写数字识别的一个实践,其中涉及到了KNN算法的原理、KD树的使用以及训练和测试数据集的处理。通过对这些内容的理解和实践,我们可以深入掌握KNN算法在...

    id_digits_object - MetaTrader 5脚本.zip

    这个“id_digits_object - MetaTrader 5脚本.zip”文件包含了一个名为"id_digits_object.mq5"的脚本,该脚本是专为MT5设计的,用于实现特定的功能。 首先,我们要理解MT5脚本的概念。MT5脚本是用MQL5语言编写的程序...

Global site tag (gtag.js) - Google Analytics