传送门

题解

倍增也好二分也好,果然复杂度只要和\(\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. linux上hadoop2.4.0安装配置

    1 环境准备 安装java-1.6(jdk) 安装ssh 1.1 安装jdk (1)下载安装jdk 在/usr/lib下创建java文件夹,输入命令: cd /usr/lib mkdir java 输 ...

  2. CF 568A(Primes or Palindromes?-暴力推断)

    A. Primes or Palindromes? time limit per test 3 seconds memory limit per test 256 megabytes input st ...

  3. hdu3076ssworld VS DDD 概率dp

    //ssworld VS DDD 两个人有血量值 hp1 , hp2  //两人掷骰子得到每一点的概率已知 //ssword赢的概率 //dp[i][j]  表示有第一个人血量为i.第二个人的血量为j ...

  4. SpringBoot学习之启动报错【This application has no explicit mapping for /error.....】

    今天做SpringBoot小例子,在请求controller层的时候出现如下问题. Whitelabel Error Page This application has no explicit map ...

  5. Python - scrapy安装中libxml2问题

    先到 http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml 下载下面三个库的 whl,然后用pip install 来安装即可 pycurl,lxml,lib ...

  6. Matlab依据样本随机数求概率曲线

    相关Matlab函数:hist, bar, cdfplot, ksdensity (1) hist函数 n = hist(Y, x)  假设x是一个向量,返回x的长度个以x为中心的,Y的分布情况. 比 ...

  7. Django 之ORM操作

    1.什么是ORM? 全称关系对象映射Object Relational Mapping(简称ORM),是通过描述面向对象与数据库之间的对应的元数据,将对象持久化的更新到数据库中. 有了ORM,就不需要 ...

  8. Codeforces Round #422 (Div. 2) A. I'm bored with life 暴力

    A. I'm bored with life     Holidays have finished. Thanks to the help of the hacker Leha, Noora mana ...

  9. ios实现倒计时的两种方法

    方法1:使用NSTimer来实现 主要使用的是NSTimer的scheduledTimerWithTimeInterval方法来每1秒执行一次timeFireMethod函数,timeFireMeth ...

  10. react native 中的redux 理解

    redux 中主要分为三大块,分别是Action Reducer 与Store. 1.Action是js的一个普通对象,是store数据的唯一来源.通过store.dispath()讲action传到 ...