列表

详情


NC24068. Data Structure

描述

将一个非负整数序列划分为段,分别计算出各段中的整数按位或的结果,然后再把这些结果按位与起来得到一个最终结果,把这个最终结果定义为这个序列的一个值。
比如序列为 ,如果划分为,那么值为。当然划分可能不止一种,所以也可能不止一个。
给定一个长度为的非负整数序列,一个整数和以下三种操作:
    1.给定一个整数,把序列中的所有数字按位或上。即
    2.给定一个整数,把序列中的所有数字按位与上。即
    3.查询当前序列最大的值。
lililalala太菜了,他希望你来帮他解决这个问题。

输入描述

第一行两个整数--序列长度和划分的段数。
第二行个整数
第三行一个整数--操作的数量。
然后行其中第行为以下三种格式之一:
--把序列中的所有数字按位或上
--把序列中的所有数字按位与上
--查询当前序列最大的值。

输出描述

对于每次查询(操作)输出一行一个整数作为查询结果。

示例1

输入:

3 2
11 30 4
5
3
1 9
3
2 22
3

输出:

10
13
4

说明:

第一次查询序列为\ [11,30,4],划分为\ [11],[30,4]时有最大值\ 10
第二次查询序列为\ [11,31,13],划分为\ [11,31],[13]时有最大值\ 13
第三次查询序列为\ [2,22,4],划分为\ [2,22],[4]时有最大值\ 4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 292ms, 内存消耗: 5880K, 提交时间: 2019-05-04 00:16:03

#include<bits/stdc++.h>
#define N 200010
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
using namespace std;

int a[N],v[32],n,m,q,fg,ans;

void spy(){
	ans=0;
	for(int i=30;i>=0;i--) if (!(fg>>i&1)){
		int tm=ans|(1<<i),cnt=0,x=0;
		for (int j=1;j<=n;j++){
			x|=a[j];
			if ((x&tm)==tm) cnt++,x=0;
		}
		if (cnt>=m) ans|=(1<<i);
	}
}

int main(){
	scc(n,m);
	for (int i=1;i<=n;i++) sc(a[i]);
	sc(q); 
	spy();
	while(q--){
		int op,x;sc(op);
		if (op<3){
			op=2-op;
			sc(x); int tm=fg;
			for (int i=0;i<=30;i++) 
				if ((x>>i&1)==op) tm|=(1<<i),v[i]=op;
			if (tm!=fg) fg=tm,spy();
		}else{
			int tm=ans;
			for (int i=0;i<=30;i++)
				if (fg>>i&1) tm|=v[i]<<i;
			printf("%d\n",tm);
		}
	}
}

上一题