FZU 2105 Digits Count(位数计算)
|
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(位数计算)的更多相关文章
- ACM: FZU 2105 Digits Count - 位运算的线段树【黑科技福利】
FZU 2105 Digits Count Time Limit:10000MS Memory Limit:262144KB 64bit IO Format:%I64d & ...
- FZU 2105 Digits Count(线段树)
Problem 2105 Digits Count Accept: 302 Submit: 1477 Time Limit: 10000 mSec Memory Limit : 262144 KB P ...
- FZU 2105 Digits Count
Problem 2105 Digits Count Accept: 444 Submit: 2139 Time Limit: 10000 mSec Memory Limit : 2621 ...
- 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 ...
- FZU 2105 Digits Count(按位维护线段树)
[题目链接] http://acm.fzu.edu.cn/problem.php?pid=2105 [题目大意] 给出一个序列,数字均小于16,为正数,每次区间操作可以使得 1. [l,r]区间and ...
- FZU Problem 2105 Digits Count
Problem Description Given N integers A={A[0],A[1],...,A[N-1]}. Here we have some operations: Operati ...
- FOJ 2105 Digits Count
题意:对一串数字进行抑或某数,和某数,或某数,统计某区间和的操作. 思路:因为化成二进制就4位可以建4颗线段树,每颗代表一位二进制. and 如果该为是1 直接无视,是0则成段赋值为0: or 如 ...
- FZU 2105 (线段树)
Problem 2105 Digits Count Problem Description Given N integers A={A[0],A[1],...,A[N-1]}. Here we h ...
- FZU-2105 Digits Count (两种标记成段更新)
题目大意:给n个0~15之间的数,有3种更新操作,1种询问操作.3种更新操作是:1.让某个闭区间的所有数字与一个0~15之间的数字进行逻辑与运算:2.让某个闭区间的所有数字与一个0~15之间的数字进行 ...
随机推荐
- gerrit docker运行失败 chown: /var/gerrit/review_site: Permission denied 【已解决】
Docker Volume 之权限管理(转) - jackluo - 博客园 http://www.cnblogs.com/jackluo/p/5783116.html 为什么在公司电脑没有问题,但在 ...
- linux之V4L2摄像头应用流程【转】
本文转载自:http://blog.csdn.net/tommy_wxie/article/details/11486907 对于v4l2,上次是在调试收音机驱动的时候用过,其他也就只是用i2c配置一 ...
- 【python cookbook】【字符串与文本】9.将Unicode文本统一表示为规范形式
问题:确保所有的Unicode字符串都拥有相同的底层 解决方案:为解决同一个文本拥有多种不同的表示形式问题,应该先将文本统一表示为规范形式,这可以通过unicodedata模块来完成, unicode ...
- Error -26612: HTTP Status-Code=500 (Internal Server Error) ...
造成HTTP-500错误,有朋友告诉我如下几个可能: 1.运行的用户数过多,对服务器造成的压力过大,服务器无法响应,则报HTTP500错误.减小用户数或者场景持续时间,问题得到解决. 2.该做关联的地 ...
- unicode转码,如:\u6d4b\u8bd5转成中文“测试”
public static void main(String[] args) { String s = "测试"; String tt = gbEncoding(s); // St ...
- Nagios监控Oralce
一.本文说明: 本文是监控本地的Oracle,其实监控远端的Oracle也是跟下面的步骤差不多的. 二.安装Nagios.Nagios插件.NRPE软件: 安装步骤可以参考<Linux下Nagi ...
- css杂记
1,font-variant: 设置文本是否为小型的大写字母,值可以为normal,small-caps; 2,a:link: 未访问过的 a:visited: 访问过的 a:active: 活动的链 ...
- JSTL.带标签体的标签,方法和例子
1. 实现 forEach 标签: 两个属性: items(集合类型, Collection), var(String 类型) doTag: 遍历 items 对应的集合 把正在遍历的对象放入到 pa ...
- Ubuntu镜像使用帮助
包括各个版本 http://mirrors.163.com/.help/ubuntu.html
- 控制窗口不能拖拉出主窗口 Dialog And Window
/* 控制窗口不能拖拉出主窗口(覆写) */var easyuiPanelOnMove = function(left, top) { if ($(this).panel('options').reS ...