Kattis - bitwise Bitwise (RMQ+尺取+树上dfs)
题意:有一个长度为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)的更多相关文章
- hdu 4123 Bob’s Race 树的直径+rmq+尺取
Bob’s Race Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Probl ...
- HDU-4123-树形dp+rmq+尺取
Bob’s Race Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- #333 Div2 Problem B Approximating a Constant Range (尺取 && RMQ || 尺取 && multiset)
题目链接:http://codeforces.com/contest/602/problem/B 题意 :给出一个含有 n 个数的区间,要求找出一个最大的连续子区间使得这个子区间的最大值和最小值的差值 ...
- hdu4123-Bob’s Race(树形dp+rmq+尺取)
题意:Bob想要开一个运动会,有n个房子和n-1条路(一棵树),Bob希望每个人都从不同的房子开始跑,要求跑的尽可能远,而且每条路只能走最多一次.Bob希望所有人跑的距离的极差不大于q,如果起点的编号 ...
- Codeforces 682C Alyona and the Tree (树上DFS+DP)
题目链接:http://codeforces.com/problemset/problem/682/C 题目大意:取树上任意一个点v,若点v的子树中有一个点u使得dist(v,u)>a[u]那么 ...
- 玲珑OJ1088【蜜汁尺取】
前言(膜法): 早上10点多开始膜的,然后到中午交了一发,感觉膜法不对啊!然后就兴起小窗了一发管理员,然后管理员给我发了in,out数据...可是太大并没有什么可取性... 还是自己试,然后发现自己搞 ...
- UVA - 11107 Life Forms (广义后缀自动机+后缀树/后缀数组+尺取)
题意:给你n个字符串,求出在超过一半的字符串中出现的所有子串中最长的子串,按字典序输出. 这道题算是我的一个黑历史了吧,以前我的做法是对这n个字符串建广义后缀自动机,然后在自动机上dfs,交上去AC了 ...
- Codeforces - 6E - Exposition - 尺取
https://codeforc.es/problemset/problem/6/E 既然可以多个log,那就直接map伺候.尺取之后要查询区间里面的最大值和最小值的差.众所周知尺取的时候要是不是有序 ...
- Gym 100703I---Endeavor for perfection(尺取)
题目链接 http://codeforces.com/problemset/gymProblem/100703/I Description standard input/outputStatement ...
随机推荐
- golang 多级json转map
func main() { jsonStr := `{"isSchemaConforming":true,"schemaVersion":0,"unk ...
- SparkCore的性能优化
1.广播变量 1.1. Spark提供的Broadcast Variable,是只读的,并且在每个节点上只会有一份副本,而不会为每个task都拷贝一份副本 1.2.它的最大作用,就是减少变量到各个节点 ...
- Django 字段更新时报错
字段更新时会报错: -------------------------------------------------------------- 无法向未定义字段添加默认值您确认添加默认值吗? 请添加 ...
- win10相机打不开,显示错误代码0xA00F4246(0x800706D9)
有时我们在不知道什么情况下电脑便会变成这个样子,当我们以为是驱动问题的时候,或许我们可以使用下面的办法解决这个问题 方法: 1.WIN键+R打开命令端,输入regedit运行 2.进入 计算机\HKE ...
- POJ3734 Block母函数入门
一段长度为n的序列,你有红黄蓝绿四种颜色的砖块,一块砖长度为1,问你铺砖的方案数,其中红黄颜色之和必须为偶数. #include <queue> #include <stack> ...
- KETTLE 主键不唯一解决方法
SELECT 某一列, COUNT( 某一列 ) FROM 表 GROUP BY 某一列 HAVING
- 【神经网络与深度学习】YOLO windows 配置《Darknet配置》
作者配置时的环境 visual studio 2013 显卡 GTX 960M CUDA 7.5 OpenCV 2.4.9 pthreadpthread 下载地址 YOLO官网 [http:// ...
- 第五周课程总结&试验报告三
第五周课程总结 一.第五周课程总结 1.this关键字 this可用于任何实例方法内指向当前对象,也可指向对其调用当前方法的对象,或者在需要当前类型对象引用时使用.当一个类的属性(成员变量)名与访问该 ...
- python list 中extend()与append()区别
def changextend(str): "print string with extend" mylist.extend([40,50,60]); print(mylist) ...
- redis 学习(3)-- String 类型
redis 学习(3)-- String 类型 String-结构 结构:Key-Value对 Value:可以是字符串.数字,也可以是二进制数组 限制:Value最大值为512MB String-常 ...