传送门

题解

倍增也好二分也好,果然复杂度只要和\(\log\)插上关系就没我啥事了……

首先由一个显而易见然而我完全没有发现的结论,设\(calc(l,r)\)表示区间\([l,r]\)的\(or\)起来加区间的\(and\)起来加区间的\(\gcd\)起来(就是题目里说的那个乱七八糟的东西)的值,那么我们固定右端点\(r\),左端点逐渐座椅的过程中,\(calc(l,r)\)的变化的次数为\(O(\log v)\),其中\(v\)是所有格子的值域

证明:左移的时候,\(or\)和\(and\)每次变化都会改变一个二进制位,最多改变\(O(\log v)\)次,而\(gcd\)因为每次都会变成自己的因子,值必然不超过之前的一半,所以总的变化次数也是\(O(\log v)\)

于是我们可以把之前的所有位置给分成\(O(\log v)\)段,其中每一段里面所有位置到当前位置的\(or,and,gcd\)都相等,这样可以用一个双向链表来维护,每次加入一个新位置的时候之前的区间不可能被拆分,只可能被合并。于是每一次加入之后合并,然后在这些所有的区间里找最优的就是了

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=3e5+5,L=19;
int Log[N],a[N],st1[N][L],st2[N][L],st3[N][L];
struct node{ll v1,v2,v3,f;}p[N],res;int las[N],nxt[N],h,t,tot;ll f[N];
int n,k;
int gcd(int x,int y){return y?gcd(y,x%y):x;}
void ins(const node &b){
p[++tot]=b,nxt[t]=tot,las[tot]=t;
t=tot,nxt[tot]=-1;
}
void del(R int pos){
nxt[las[pos]]=nxt[pos];
pos==t?t=las[pos]:las[nxt[pos]]=las[pos];
}
int query_or(R int l,R int r){
int k=Log[r-l+1];
return st1[l][k]|st1[r-(1<<k)+1][k];
}
int query_and(R int l,R int r){
int k=Log[r-l+1];
return st2[l][k]&st2[r-(1<<k)+1][k];
}
int query_gcd(R int l,R int r){
int k=Log[r-l+1];
return gcd(st3[l][k],st3[r-(1<<k)+1][k]);
}
void clr(){
tot=h=t=0;
memset(nxt,0,sizeof(nxt)),memset(las,0,sizeof(las));
memset(f,0xef,sizeof(f)),nxt[0]=-1;
}
int main(){
// freopen("testdata.in","r",stdin);
int T=read();fp(i,2,N-5)Log[i]=Log[i>>1]+1;
while(T--){
clr();
n=read(),k=read();
fp(i,1,n)st1[i][0]=st2[i][0]=st3[i][0]=a[i]=read();
fp(i,1,k)f[i-1]=read();
for(R int j=1;(1<<j)<=n;++j)fp(i,1,n-(1<<j)+1){
st1[i][j]=st1[i][j-1]|st1[i+(1<<j-1)][j-1];
st2[i][j]=st2[i][j-1]&st2[i+(1<<j-1)][j-1];
st3[i][j]=gcd(st3[i][j-1],st3[i+(1<<j-1)][j-1]);
}
fp(i,k,n){
int pos=nxt[h];
while(pos>=0){
p[pos].v1|=a[i],p[pos].v2&=a[i],p[pos].v3=gcd(p[pos].v3,a[i]);
pos=nxt[pos];
}res={query_or(i-k+1,i),query_and(i-k+1,i),query_gcd(i-k+1,i),f[i-k]};
ins(res),pos=nxt[h];
while(pos>=0&&nxt[pos]>=0){
if(p[pos].v1==p[nxt[pos]].v1&&
p[pos].v2==p[nxt[pos]].v2&&
p[pos].v3==p[nxt[pos]].v3)
cmax(p[pos].f,p[nxt[pos]].f),del(nxt[pos]);
pos=nxt[pos];
}pos=nxt[h];
while(pos>=0)cmax(f[i],p[pos].v1+p[pos].v2+p[pos].v3+p[pos].f),pos=nxt[pos];
}printf("%lld\n",f[n]);
}return 0;
}

P5167 xtq的神笔的更多相关文章

  1. P5168 xtq玩魔塔 [克鲁斯卡尔重构树+带修莫队]

    P5168 xtq玩魔塔 又是码农题- 利用克鲁斯卡尔重构树的性质 我们就可以得出 \(dep\) 值小的,肯定比 \(dep\) 大的值要优. 于是第二问就可以直接 LCA 求出来了- 至于第三问, ...

  2. 【Luogu P5168】xtq玩魔塔(Kruskal 重构树 & 树状数组 & set)

    Description 给定一个 \(n\) 个顶点,\(m\) 条边的无向联通图,点.边带权. 先有 \(q\) 次修改或询问,每个指令形如 \(\text{opt}\ x\ y\): \(\tex ...

  3. 学习大神笔记之 “MyBatis学习总结(一)”

    1.准备工作 软件:eclipse. mysql .navicat for mysql 包:mybatis-3.1.1.jar   mysql-connector-java-5.1.7-bin.jar ...

  4. Luogu P5168 xtq玩魔塔

    这题不错啊,结合了一些不太传统的姿势. 首先看到题目有一问从一个点到另一个点边权最小值.想到了什么? 克鲁斯卡尔生成树+倍增?好吧其实有一个更常用NB的算法叫克鲁斯卡尔重构树 (不会的可以看dalao ...

  5. 设计模式--单例模式(学习Learning hard大神笔记实践)

    根据大神博客园中的文章,自己亲手敲了一遍,对每个解说点都自己动手进行实践,收获颇丰,谢谢Learning hard大神,原文地址http://www.cnblogs.com/zhili/p/Desig ...

  6. [洛谷P5169]xtq的异或和

    题目大意:给你一张$n(n\leqslant10^5)$个点$m(m\leqslant3\times10^5)$条边的无向图,每条边有一个权值,$q(q\leqslant2^{18})$次询问,每次询 ...

  7. [洛谷P5166]xtq的口令

    题目大意:给出一张有向图,保证任何时候边都是从编号大的向编号小连.两个操作: $1\;l\;r:$表示若编号在区间$[l,r]$内的点被染色了,问至少还需要染多少个点才可以使得整张图被染色.一个点会被 ...

  8. P5169 xtq的异或和(FWT+线性基)

    传送门 我咋感觉我学啥都是白学-- 首先可以参考一下这一题,从中我们可以知道只要知道两点间任意一条路径以及整个图里所有环的线性基,就可以得知这两个点之间的所有路径的异或和 然而我好像并不会求线性基能张 ...

  9. P5168 xtq玩魔塔

    传送门 其实就是板子--只要会克鲁斯卡尔重构树和带修莫队就可以了 这么想着的我就调了将近一个下午-- 思路其实比较清晰,然而码量很大,细节贼多-- 不难看出只在最小生成树上走最优,于是建出克鲁斯卡尔重 ...

随机推荐

  1. mysql 安装与启动

    1.下载mysql installer 2.安装 一直点next,直到finish. 3.安装时的配置 安装完后,选择立即开始配置. 选择standard configuration 勾选安装mysq ...

  2. HDU 3342 Legal or Not (最短路 拓扑排序?)

    Legal or Not Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  3. hud 1465、2049、2045 (递推)[含简单C(n,m) n!的写法]

    C - 不容易系列之一 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit  ...

  4. Hibernate - DetachedCriteria 的完整用法(转)

    现在对 Hibernate的Criteria 的用法进行总结:     Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口,下面提供了 Crite ...

  5. IE浏览器部分版本不支持background-size属性问题

    background-size是CSS3新增的属性,但是IE8以下还是不支持,可以通过滤镜来实现这样的一个效果 background-size:contain; // 缩小图片来适应元素的尺寸(保持像 ...

  6. SpringBoot项目 部署到服务器的tomcat下

    把spring-boot项目按照平常的web项目一样发布到tomcat容器下 一.修改pom文件 修改打包方式 修改或增加maven插件 注意: 二.移除嵌入式tomcat插件 三.添加servlet ...

  7. MapReduce算法形式五:TOP—N

    案例五:TOP—N 这个问题比较常见,一般都用于求前几个或者后几个的问题,shuffle有一个默认的排序是正序的,但如果需要逆序的并且暂时还不知道如何重写shuffle的排序规则的时候就用以下方法就行 ...

  8. queue — A synchronized queue class

    https://docs.python.org/3.6/library/queue.html https://github.com/python/cpython/blob/3.6/Lib/queue. ...

  9. [翻译]Unity中的AssetBundle详解(三)

    构建AssetBundles 在AssetBundle工作流程的文档中,我们有一个示例代码,它将三个参数传递给BuildPipeline.BuildAssetBundles函数.让我们更深入地了解我们 ...

  10. Linux时间子系统之三:时间的维护者:timekeeper【转】

    本文转载自:http://blog.csdn.net/droidphone/article/details/7989566 本系列文章的前两节讨论了用于计时的时钟源:clocksource,以及内核内 ...