题目链接


题目大意:

给你一个序列{a}\{a\}{a},每次询问一个区间[l,r][l,r][l,r]
问你这个区间里面的数是否可以分成两部分使得一部分的AND=AND=AND=另一部分的OROROR


解题思路:

  1. 这个题思路很妙:
  2. 首先我们知道对于&\&&操作数越多只会越&\&&越小,而∣|∣就是相反的
  3. 那么我们可以假设这个区间里面的数可以分成两部分,那么假设最后的答案是ansansans
  4. 假设ansansans中有xxx个1,那么对于区间里面数包含的1的个数大过xxx的话那么一定是执行&\&&操作,反过来同理小的就是∣|∣操作。
  5. 但是如果是刚好为xxx怎么办?,它是&\&&还是∣|∣呢?
  6. 这里还要再讨论一下:
  7. 如果刚好为xxx的数是不同的?那么它们一定是要划分到一个集合里面(如果它们在不同的集合里面肯定结果不会相等)
  8. 如果xxx的数都是一样的那么我们就可以划分到两边,也可以在一边,分成两边的时候你最起码个数要大于1

那么思路就很明显了:我们枚举x∈[0,30]x\in[0,30]x∈[0,30],然后[0,x−1][0,x-1][0,x−1]里面的数求∣|∣,[x+1,30][x+1,30][x+1,30]里面的数取&\&&,那么对于xxx我们要记录里面的数是否是同一个数。和数的个数

那么我们就可以开303030棵线段树。每个维护区间里面1个数为xxx的各种信息。


AC code

#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 800010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {read(first);read(args...);
}
struct inf {int a, b, c;
}all;
struct Segtree {int OR[maxn];int AND[maxn];int is[maxn];// 区间里面的数是否是一种而已?int sum[maxn];//区间数额个数inline void pushup(int rt) {sum[rt] = sum[rt<<1] + sum[rt<<1|1];  if(!is[rt<<1]) is[rt] = is[rt<<1|1];else if(!is[rt<<1|1]) is[rt] = is[rt<<1];else if(is[rt<<1|1] != is[rt<<1]) is[rt] = -1;else is[rt] = is[rt<<1];OR[rt] = (OR[rt<<1] | OR[rt<<1|1]);AND[rt] = (AND[rt<<1] & AND[rt<<1|1]);}void build(int rt, int l, int r) {if(l == r) {OR[rt] = sum[rt] = is[rt] = 0;AND[rt] = (1<<30)-1;return;}build(Lson);build(Rson);pushup(rt);} void insert(int rt, int l, int r, int pos, int val) {if(l == r) {sum[rt] = 1;is[rt] = OR[rt] = AND[rt] = val;return;}if(pos <= mid) insert(Lson,pos,val);else insert(Rson,pos,val);pushup(rt);}inline inf mege(inf a, inf b) {inf res;res.a = a.a & b.a;res.b = a.b | b.b;res.c = a.c + b.c;return res;}inf quaryAND_OR_SUM(int rt, int l, int r, int L, int R) {if(L <= l && R >= r) return (inf){AND[rt],OR[rt],sum[rt]};inf res = {(1<<31)-1,0,0};if(L <= mid) res = mege(quaryAND_OR_SUM(Lson,L,R),res);if(R > mid) res = mege(quaryAND_OR_SUM(Rson,L,R),res);return res;}int quaryis(int rt, int l, int r, int L, int R) {if(L <= l && R >= r) return is[rt];if(L > mid) return quaryis(Rson,L,R);else if(R <= mid) return quaryis(Lson,L,R);else {int lson = quaryis(Lson,L,R);int rson = quaryis(Rson,L,R);if(lson == -1 || rson == -1) return -1;if(!lson) return rson;if(!rson) return lson;if(lson == rson) return lson;return -1;}}}sgt[40];
// n个点,q个询问,Less[i]是[0,i]里面所有数的OR,eq[i]是x=i时候的数的AND和OR
int n, q, AND[40], OR[40], arr[maxn], Less[40], more;
bool eqis[40], isOR[40], flag, isAND;
PII eq[40];
int main() {read(n,q);for(int i = 0; i <= 30; ++ i) sgt[i].build(1,1,n); //建线段树for(int i = 1; i <= n; ++ i) {read(arr[i]);int num = 0;for(int j = 30; j >= 0; j --) {// 获取每个数的1的个数if(arr[i] >> j & 1)num ++;}   sgt[num].insert(1,1,n,i,arr[i]); // 插到对应位置去} while(q --) {int l, r;read(l,r);for(register int i = 0; i <= 30; ++ i) {// 枚举xinf is = sgt[i].quaryAND_OR_SUM(1,1,n,l,r);// 获取[l,r]区间里面的AND OR sumAND[i] = is.a;OR[i] = is.b;eqis[i] = is.c; // x=i是否存在isOR[i] = is.c; //是否OR过了也就是[0,i]是否有数if(i) isOR[i] |= isOR[i-1];(i != 0) ? (Less[i] = Less[i-1] | OR[i]) : (Less[i] = OR[i]); //维护前缀ORif(!is.c) continue;//如果下面没数了int _is = sgt[i].quaryis(1,1,n,l,r);eq[i] = {AND[i],OR[i]};//x = i时候数的 AND 和 ORif(is.c >= 2 && _is != -1) eq[i].first = -2;// 这里设置-2是为了判断那个x全是同一个数并且个数>= 2}flag = 0, isAND = 0; // flag是答案,isAND就是判断是否AND过了more = (1<<31)-1;for(register int i = 30; i >= 1 && !flag; -- i) {//枚举&的位置i-2, i-1 和 imore &= AND[i];isAND |= eqis[i];if(i == 1) break;if(!eqis[i-1]) { // 如果没有x=i-1看[0,i-2]和[i,30]是否相等if(more == Less[i-2] && isAND && isOR[i-2]) flag = 1;continue;}if(eq[i-1].first == -2) {if((Less[i-2]|eq[i-1].second) == (more&eq[i-1].second)) flag = 1;eq[i-1].first = eq[i-1].second; // 记得复原eq[i-1].first}if(isAND && (Less[i-2] | eq[i-1].second) == more) flag = 1;if(isOR[i-2] && (more & eq[i-1].first) == Less[i-2]) flag = 1;//分到AND和OR集合}if(eqis[30]) {//特判两个边界if(eq[30].first == -2) {eq[30].first = eq[30].second;if((Less[29]|eq[30].second) == eq[30].second) flag = 1;} if(isOR[29] && Less[29] == eq[30].first) flag = 1;} if(eqis[0]) {if(eq[0].first == -2) {if((more&eq[0].second) == eq[0].second) flag = 1;} if(isAND && more == eq[0].second) flag = 1;}puts(flag ? "YES" : "NO"); }return 0;
}
/*
5 1
1 1 1 1 1
1 27 1
4 2 9 6 2 4 2
5 64 1
4 4 3 0
2 3*/

线段树 ---- H. AND = OR (或和与的性质之1的个数 + 线段树)相关推荐

  1. b+树时间复杂度_第15期:索引设计(索引组织方式 B+ 树)

    谈到索引,大家并不陌生.索引本身是一种数据结构,存在的目的主要是为了缩短数据检索的时间,最大程度减少磁盘 IO. 任何有数据的场景几乎都有索引,比如手机通讯录.文件系统(ext4xfsfs).数据库系 ...

  2. 字典树实现_【Leetcode每日打卡】单词的压缩编码 Trie(字典树)入门

    一.前言(鸡汤(一段废..话..可以跳过啦)) 同学们好!没想到我这个小小的公众号破千粉啦,对于大佬们而言或许不值一提,但是对我而言是一个莫大的鼓舞!更加坚定了我持续输出优质内容的决心.希望我们都能每 ...

  3. 树和二叉树定义、基本术语和性质

    树的定义和基本术语 •树:是一类重要的非线性数据结构,是以分支关系定义的层次结构. •根:树(tree)是n(n>=0)个结点的有限集T,对于非空树,其中有且仅有一个特定的结点,称为树的根(ro ...

  4. 线索树找*p的中序后继且中序遍历 二叉线索树

    //线索树找*p的中序后继且中序遍历 二叉线索树 #define thread 1 #define link 0 typedef struct Bt{char data;struct Bt *lc;/ ...

  5. 索引(B+树)、B+树一个节点有多大?(一千万条数据,B+树多高?)

    目录 1. 谈谈对索引的理解 2. B树和B+树的区别?为什么使用B+树?(B+树底层文件是怎么存储的) 3. MySQL为什么要用B+树存储索引?而不用平衡二叉树(红黑树).Hash索引(散列表). ...

  6. Algorithm:树结构(二叉树/多路查找树/字典树)的简介、具体结构(FBT/CBT/BST/BBT/Heap/Huffman、B树/B+树/R树、字典树)及其运算(增删查/遍历/旋转)、代码实现

    Algorithm:树结构(二叉树/多路查找树/字典树)的简介.具体结构(FBT/CBT/BST/BBT/Heap/Huffman.B树/B+树/R树.字典树)及其运算(增删查/遍历/旋转).代码实现 ...

  7. 线段树 ---- 2021牛客多校第一场 J Journey among Railway Stations [线段树维护区间可行性判断]

    题目链接 题目大意: 一段路上有 NNN 个点,每个点有一个合法时间段[ui,vi][u_i,v_i][ui​,vi​],相邻两个点有一个长度wiw_iwi​.有qqq次询问,每次询问,在 [ui,v ...

  8. Super Mario HDU - 4417(主席树解决区间数字小于k的个数||线段树+离线)

    Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in ...

  9. poj 2352 Stars 线段树(先建后查/边建边查)/树状数组三种方法思路详解,带你深入了解线段树难度⭐⭐⭐★

    poj 2352 Stars 目录 poj 2352 Stars 1.树状数组 2.线段树,先建树后查找 3.线段树,边建树边查找 Description Astronomers often exam ...

最新文章

  1. 继续过中等难度.0309
  2. 对css float 浮动的学习心得
  3. 北京黑马计算机培训宿舍图案,黑马经典图形!
  4. 【 .NET Core 3.0 】框架之二 || 后端项目搭建
  5. 计算机二级web题目(6)--动态网页技术概述
  6. java integer_Java之Integer类
  7. Linux IO复用:select、poll、epoll的理解与对比
  8. Linux 原来实现一个shell这么容易!(史上最简单详细)
  9. 探讨IOS应用在中国的盈利模式
  10. 关于Unity中Mesh网格的详解
  11. JavaScript的DOM编程--01--js代码的写入位置
  12. 【渝粤教育】国家开放大学2018年秋季 0690-22T化工原理及实验 参考试题
  13. 第一个android应用程序,深入学习Android 第一个应用程序
  14. PRML学习总结(1)——Introduction
  15. 定值保险计算举例_保险学计算题
  16. 163个人域名邮箱申请,163个人邮箱怎么注册创建
  17. UVALive - 2911 Maximum
  18. rk3288 android 6.0固件,RK3288固件升级教程
  19. 《那些年啊,那些事——一个程序员的奋斗史》——40
  20. 描述统计—AppStore app分析

热门文章

  1. python记录当前系统时间 生成照片直接命名
  2. 转,大佬关于虚拟内存与物理内存关系讲解。
  3. Linux CENTOS7 Linux ntopng流量监控、端口监控、服务监控管理系统 安装过程以及示例!另外附带CENTOS6的安装过程!
  4. 注意力机制原理及其模型发展和应用
  5. 编程能力如何突飞猛进?
  6. 【OpenCV 4开发详解】分割图像——Mean-Shift分割算法
  7. 步步为营 .NET 设计模式学习笔记 六、Adapter(适配器模式)
  8. HBase安装配置以及Java操作hbase
  9. 线程关键字、锁、同步集合笔记
  10. 数据挖掘视频教程下载