题意:有一个长度为n的序列,让你把它分成k段,段内元素取or,段间取and,求能够得到的最大值。

这个算法是我和xz场上yy出来的,然而时间不够了没写出来,而且时间复杂度是$O(nlogn+nlogA)$的比官方题解都要低...(但是常数大了点)

设最大值为ans,我们假设S&ans=S,看看S能否用k条线段凑出来,则将原问题转化成了一个判定问题。从高到低一位一位地考虑,最多只需进行$O(logA)$次判定。

如何进行判定呢?

首先将原数组复制一倍接到后面,然后进行两次尺取。第一次求出每个左端点l所对应的能够覆盖S的最小的右端点r并把它作为一条线段放进数组里(能够覆盖S的意思是S的每一位上的1都可以在[l,r]区间里的某个元素中取到,可以用RMQ预处理区间or然后$O(1)$判断),第二次则对这些线段进行尺取,求出每条线段右边第一条和它不相交的线段,将每条线段与这样的线段连边,可以得到一棵树(或者森林,若为森林则将所有树和一个虚节点连边即可变成一棵树),只需要检查一下这棵树上是否有一个结点的l和与它距离为k的父亲结点的r的区间长度r-l+1是否小于n,从根节点dfs一遍即可。

代码:(我写了两份,第一份怕爆栈所以手写了数组模拟栈,第二份是普通的dfs)

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+;
int n,k,a[N],ST[N][],Log[N],nl,hd[N],ne,q[N],tp;
void build() {
for(int i=; i<=*n; ++i)ST[i][]=a[i];
for(int k=; k<=Log[*n]; ++k)
for(int i=; i+(<<k)-<=*n; ++i)
ST[i][k]=ST[i][k-]|ST[i+(<<(k-))][k-];
}
int qry(int L,int R) {
int k=Log[R-L+];
return ST[L][k]|ST[R-(<<k)+][k];
}
struct D {int l,r;} line[N];
struct E {int v,nxt;} e[N];
struct ND {int u,dep;} sta[N];
void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
bool dfs() {
sta[tp=]= {nl,};
while(~tp) {
int u=sta[tp].u,dep=sta[tp--].dep;
q[dep]=u;
if(dep>=k&&line[q[dep-k+]].r-line[u].l+<=n)return ;
for(int i=hd[u]; ~i; i=e[i].nxt)sta[++tp]= {e[i].v,dep+};
}
return ;
}
bool ok(int S) {
nl=;
for(int i=,j=; i<=*n; ++i) {
if(j<i)j=i;
for(; j<=*n&&(qry(i,j)&S)!=S; ++j);
if(j<=*n)line[nl++]= {i,j};
}
for(int i=; i<=nl; ++i)hd[i]=-;
ne=;
for(int i=,j=; i<nl; ++i) {
for(; j<nl&&line[j].l<=line[i].r; ++j);
addedge(j,i);
}
return dfs();
}
int solve() {
int ret=;
for(int i=; i>=; --i)if(ok(ret|(<<i)))ret|=<<i;
return ret;
}
int main() {
Log[]=-;
for(int i=; i<N; ++i)Log[i]=Log[i>>]+;
scanf("%d%d",&n,&k);
for(int i=; i<=n; ++i)scanf("%d",&a[i]);
for(int i=; i<=n; ++i)a[i+n]=a[i];
build();
printf("%d\n",solve());
return ;
}
 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+;
int n,k,a[N],ST[N][],Log[N],nl,hd[N],ne,q[N];
void build() {
for(int i=; i<=*n; ++i)ST[i][]=a[i];
for(int k=; k<=Log[*n]; ++k)
for(int i=; i+(<<k)-<=*n; ++i)
ST[i][k]=ST[i][k-]|ST[i+(<<(k-))][k-];
}
int qry(int L,int R) {
int k=Log[R-L+];
return ST[L][k]|ST[R-(<<k)+][k];
}
struct D {int l,r;} line[N];
struct E {int v,nxt;} e[N];
void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
bool dfs(int u,int dep) {
q[dep]=u;
if(dep>=k&&line[q[dep-k+]].r-line[u].l+<=n)return ;
for(int i=hd[u]; ~i; i=e[i].nxt)if(dfs(e[i].v,dep+))return ;
return ;
}
bool ok(int S) {
nl=;
for(int i=,j=; i<=*n; ++i) {
if(j<i)j=i;
for(; j<=*n&&(qry(i,j)&S)!=S; ++j);
if(j<=*n)line[nl++]= {i,j};
}
for(int i=; i<=nl; ++i)hd[i]=-;
ne=;
for(int i=,j=; i<nl; ++i) {
for(; j<nl&&line[j].l<=line[i].r; ++j);
addedge(j,i);
}
return dfs(nl,);
}
int solve() {
int ret=;
for(int i=; i>=; --i)if(ok(ret|(<<i)))ret|=<<i;
return ret;
}
int main() {
Log[]=-;
for(int i=; i<N; ++i)Log[i]=Log[i>>]+;
scanf("%d%d",&n,&k);
for(int i=; i<=n; ++i)scanf("%d",&a[i]);
for(int i=; i<=n; ++i)a[i+n]=a[i];
build();
printf("%d\n",solve());
return ;
}

Kattis - bitwise Bitwise (RMQ+尺取+树上dfs)的更多相关文章

  1. hdu 4123 Bob’s Race 树的直径+rmq+尺取

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Probl ...

  2. HDU-4123-树形dp+rmq+尺取

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. #333 Div2 Problem B Approximating a Constant Range (尺取 && RMQ || 尺取 && multiset)

    题目链接:http://codeforces.com/contest/602/problem/B 题意 :给出一个含有 n 个数的区间,要求找出一个最大的连续子区间使得这个子区间的最大值和最小值的差值 ...

  4. hdu4123-Bob’s Race(树形dp+rmq+尺取)

    题意:Bob想要开一个运动会,有n个房子和n-1条路(一棵树),Bob希望每个人都从不同的房子开始跑,要求跑的尽可能远,而且每条路只能走最多一次.Bob希望所有人跑的距离的极差不大于q,如果起点的编号 ...

  5. Codeforces 682C Alyona and the Tree (树上DFS+DP)

    题目链接:http://codeforces.com/problemset/problem/682/C 题目大意:取树上任意一个点v,若点v的子树中有一个点u使得dist(v,u)>a[u]那么 ...

  6. 玲珑OJ1088【蜜汁尺取】

    前言(膜法): 早上10点多开始膜的,然后到中午交了一发,感觉膜法不对啊!然后就兴起小窗了一发管理员,然后管理员给我发了in,out数据...可是太大并没有什么可取性... 还是自己试,然后发现自己搞 ...

  7. UVA - 11107 Life Forms (广义后缀自动机+后缀树/后缀数组+尺取)

    题意:给你n个字符串,求出在超过一半的字符串中出现的所有子串中最长的子串,按字典序输出. 这道题算是我的一个黑历史了吧,以前我的做法是对这n个字符串建广义后缀自动机,然后在自动机上dfs,交上去AC了 ...

  8. Codeforces - 6E - Exposition - 尺取

    https://codeforc.es/problemset/problem/6/E 既然可以多个log,那就直接map伺候.尺取之后要查询区间里面的最大值和最小值的差.众所周知尺取的时候要是不是有序 ...

  9. Gym 100703I---Endeavor for perfection(尺取)

    题目链接 http://codeforces.com/problemset/gymProblem/100703/I Description standard input/outputStatement ...

随机推荐

  1. JavaScript Cookie常用设置

    cookie是一种早期的客户端存储机制,起初是针对服务器端脚本设计使用的,只适合存储少量文本数据.从最底层来看,作为HTTP协议的一种扩展实现它.cookie数据会自动在Web浏览器和Web服务器之间 ...

  2. 【学习笔记】APP页面,随机选择一个选项

    如下页面,一个测评功能,30个题目,每题的答案选项一样: 要实现每题自动随机选择一个答案 方法一:定义一个5个选项的列表,循环30次,然后使用random.shuffle打乱列表顺序,根据列表元素定位 ...

  3. 【MapReduce】一、MapReduce简介与实例

    (一)MapReduce介绍 1.MapReduce简介   MapReduce是Hadoop生态系统的一个重要组成部分,与分布式文件系统HDFS.分布式数据库HBase一起合称为传统Hadoop的三 ...

  4. Java生成二维码连接

    本文使用的是Goodge的zxing 添加maven依赖 <dependency> <groupId>com.google.zxing</groupId> < ...

  5. python AI换脸 用普氏分析法(Procrustes Analysis)实现人脸对齐

    1.图片效果 2.原代码 # !/usr/bin/python # -*- coding: utf-8 -*- # Copyright (c) 2015 Matthew Earl # # Permis ...

  6. C++学习笔记-面向对象模型探究

    C++中的class从面向对象理论出发,将变量(属性)和函数(方法)集中定义在一起,用于描述现实世界中的类.从计算机的角度,程序依然由数据段和代码段构成.那么C++编译器如何完成面向对象理论到计算机程 ...

  7. [转帖]Oracle 数据库官方不支持VMWare

    Oracle 数据库官方不支持VMWare [日期:2014-05-13] 来源:Linux社区  作者:myhuaer [字体:大 中 小]   https://www.linuxidc.com/L ...

  8. 【案例分享】使用ActiveReports报表工具,在.NET MVC模式下动态创建报表

    提起报表,大家会觉得即熟悉又陌生,好像常常在工作中使用,又似乎无法准确描述报表.今天我们来一起了解一下什么是报表,报表的结构.构成元素,以及为什么需要报表. 什么是报表 简单的说:报表就是通过表格.图 ...

  9. 不同浏览器之间的javascript和css兼容性问题

    po主手头维护的网站是上世纪的作品.当时约摸ie所占的市场份额相当大,以至于开发人员都没有考虑到浏览器兼容性问题(这不科学!).怎奈po主是个强迫症阿.最近在修改的时候,还是没忍住,把兼容性问题解决了 ...

  10. 小菜鸟之JAVA输入输出

    Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观 ...