P5167 xtq的神笔
倍增也好二分也好,果然复杂度只要和\(\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的神笔的更多相关文章
- P5168 xtq玩魔塔 [克鲁斯卡尔重构树+带修莫队]
P5168 xtq玩魔塔 又是码农题- 利用克鲁斯卡尔重构树的性质 我们就可以得出 \(dep\) 值小的,肯定比 \(dep\) 大的值要优. 于是第二问就可以直接 LCA 求出来了- 至于第三问, ...
- 【Luogu P5168】xtq玩魔塔(Kruskal 重构树 & 树状数组 & set)
Description 给定一个 \(n\) 个顶点,\(m\) 条边的无向联通图,点.边带权. 先有 \(q\) 次修改或询问,每个指令形如 \(\text{opt}\ x\ y\): \(\tex ...
- 学习大神笔记之 “MyBatis学习总结(一)”
1.准备工作 软件:eclipse. mysql .navicat for mysql 包:mybatis-3.1.1.jar mysql-connector-java-5.1.7-bin.jar ...
- Luogu P5168 xtq玩魔塔
这题不错啊,结合了一些不太传统的姿势. 首先看到题目有一问从一个点到另一个点边权最小值.想到了什么? 克鲁斯卡尔生成树+倍增?好吧其实有一个更常用NB的算法叫克鲁斯卡尔重构树 (不会的可以看dalao ...
- 设计模式--单例模式(学习Learning hard大神笔记实践)
根据大神博客园中的文章,自己亲手敲了一遍,对每个解说点都自己动手进行实践,收获颇丰,谢谢Learning hard大神,原文地址http://www.cnblogs.com/zhili/p/Desig ...
- [洛谷P5169]xtq的异或和
题目大意:给你一张$n(n\leqslant10^5)$个点$m(m\leqslant3\times10^5)$条边的无向图,每条边有一个权值,$q(q\leqslant2^{18})$次询问,每次询 ...
- [洛谷P5166]xtq的口令
题目大意:给出一张有向图,保证任何时候边都是从编号大的向编号小连.两个操作: $1\;l\;r:$表示若编号在区间$[l,r]$内的点被染色了,问至少还需要染多少个点才可以使得整张图被染色.一个点会被 ...
- P5169 xtq的异或和(FWT+线性基)
传送门 我咋感觉我学啥都是白学-- 首先可以参考一下这一题,从中我们可以知道只要知道两点间任意一条路径以及整个图里所有环的线性基,就可以得知这两个点之间的所有路径的异或和 然而我好像并不会求线性基能张 ...
- P5168 xtq玩魔塔
传送门 其实就是板子--只要会克鲁斯卡尔重构树和带修莫队就可以了 这么想着的我就调了将近一个下午-- 思路其实比较清晰,然而码量很大,细节贼多-- 不难看出只在最小生成树上走最优,于是建出克鲁斯卡尔重 ...
随机推荐
- vim note (1)
'vim' go into the vim mode 'i' 'a' 's' is means insert mode 'v' is means visual mode 'esc' is mea ...
- C++类中static修饰的函数的使用
//在C++中应该养成习惯:只用静态成员函数引用静态成员数据,而不引用非静态成员数据 #include <iostream>using namespace std;class st_inf ...
- Swift开发教程--怎样播放图片动画
废话少说,直接上代码: var barsAnim = UIImageView(frame: self.view.frame); barsAnim.animationImages = NSArray() ...
- 2016/06/13 phpexcel 未完待续
①准备工作: 1,php版本不能太低 2,去官网下载PHPExcel插件 http://phpexcel.codeplex.com/ 3,解压后提取classes文件夹到工作目录,并重命名为PH ...
- hibernate面试点
1.谈谈你对hibernate的认识和理解 01.全自动的ORM框架 02.子项目 03.面向对象的思想来解决操作数据库 01.hibernate是一个开放源代码的对象关系映射(ORM)框架,它对JD ...
- POJ2942 Knights of the Round Table 点双连通分量 二分图判定
题目大意 有N个骑士,给出某些骑士之间的仇恨关系,每次开会时会选一些骑士开,骑士们会围坐在一个圆桌旁.一次会议能够顺利举行,要满足两个条件:1.任意相互憎恨的两个骑士不能相邻.2.开会人数为大于2的奇 ...
- URL 下载
package URL; import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import j ...
- html的书写规范,有哪些注意点
1.最开始的声明格式与编码格式,注意html5与和html4.0的区别,注意对不同浏览器的渲染作用: 2.<head></head>标签中的相关内容的编写: 3.确保引入的jq ...
- iOS——多线程编程详细解析
基本定义: 程序:由代码生成的可执行应用.(例如QQ.app) 进程:一个正在运行的程序可以看做是一个进程. (例如:正在运行的QQ 就是一个进程),进程拥有独立运行所需要的全部资源. 线程: 程序中 ...
- hdu 2112 HDU Today 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2112 题目意思:又是求最短路的,不过结合埋字符串来考查. 受之前1004 Let the Balloo ...