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
Sample Input
Sample Output
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
NVIDIA DIGITS安装教程
这个压缩包主要是我用Anaconda创建py27环境下安装DIGITS的过程,其中主要自己安装过程中的各种非常细节的踩坑和安装细节流程等。最后的安装配置都是OK的,不过最后由于我笔记本中的python图像处理库scikit-image的...
Laravel开发-unique-digits 为PHP的不同需求(票号和其他)创建数字值。
pi_million_digits, python课程文件读取用,codeforge下载
一个给定的正整数,循环的将每一位相加,只要得到的结果是大于10的数,就继续循环相加
Nvidia 中 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中解决Can't pickle <class 'caffe.proto.caffe_pb2.NetParameter'>: it's not the same object as caffe.proto.caffe_pb2.NetParameter问题的解决方法,我将需要修该的地方截图了,附带了一个原...
北大POJ3373-Changing Digits【DFS+强剪枝】 解题报告+AC代码
mnist_digits.7z 每个文件是一个数字的01矩阵,一个文件对应一个数字,文件名第一个字符为对应的数字。 无须积分
mnist+digits数据集使用图像增强共同训练的Python源代码,可以让识别准确率达到99%,即使是自己的手写数字也可以!
tensorflowvisu_digits
统信系统UOS资源包4digits_1.1.4-1+b1 资源列表: 4digits_1.1.4-1+b1_amd64.deb 4digits_1.1.4-1+b1_arm64.deb 4digits_1.1.4-1+b1_i386.deb 4digits_1.1.4-1+b1_mips64el.deb 4digits_1.1.4.orig.tar.gz 4digits_...
This article describes some of the methods used to get the world record of the computation of the digits of digits using an inexpensive desktop computer.
手写数字0-9的样本数据,每个样本类型500,共5000个;每张图片的大小是20*20 .jpg格式;来源于opencv中手写数字的大图截取
kaggle上提供的数据集,包含了5000个数字的图片,以及对图片的标注,其中图片以灰度值保存在表格里。