首页 技术 正文
技术 2022年11月15日
0 收藏 431 点赞 3,888 浏览 2784 个字

传送门

题解

倍增也好二分也好,果然复杂度只要和\(\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;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,083
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,558
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,407
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,180
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,817
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,900