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玩魔塔
传送门 其实就是板子--只要会克鲁斯卡尔重构树和带修莫队就可以了 这么想着的我就调了将近一个下午-- 思路其实比较清晰,然而码量很大,细节贼多-- 不难看出只在最小生成树上走最优,于是建出克鲁斯卡尔重 ...
随机推荐
- Loadrunner IP欺骗
一.为什么要设置IP欺骗 1. 当某个IP的訪问过于频繁,或者訪问量过大时,server会拒绝訪问请求.这时候通过IP欺骗能够添加訪问频率和訪问量,以达到压力測试的效果. 2. 某些server配置了 ...
- c++面试题目(3)
这些东西有点烦,有点无聊.如果要去C++面试就看看吧.几年前网上搜索的.刚才看到,就整理一下,里面有些被我改了,感觉之前说的不对或不完善. 1.求下面函数的返回值( 微软) int func(x) ...
- 走入asp.net mvc不归路:[5]Action的返回
asp.net mvc提供了多种返回方式,一方面使得视图可以重用,另一方面灵活强大,有直接返回视图,返回Json,返回文件流,返回到相同Controller的Action,返回到另一个Controll ...
- 解决Sql server分页时第二页以上查询结果不正常的问题
有100个产品,其中最高价格的为200元,而200元的产品共有40个, 现在好了,对每页30进行分页: declare @PageSize int--30 declare @Page int decl ...
- Computer form factor
http://en.wikipedia.org/wiki/Motherboard_form_factor Computer form factor From Wikipedia, the free e ...
- React Native安装
1.安装 1.1 安装Node.js 下载安装即可 1.2 安装Homebrew 终端中执行: $ /usr/bin/ruby -e "$(curl -fsSL https://raw.gi ...
- HDOJ_ How can I read input data until the end of file ?
Language C C++ Pascal To read numbers int n;while(scanf("%d", &n) != EOF){ ...} int n; ...
- poj 1821 Fence(单调队列优化DP)
poj 1821 Fence \(solution:\) 这道题因为每一个粉刷的人都有一块"必刷的木板",所以可以预见我们的最终方案里的粉刷匠一定是按其必刷的木板的顺序排列的.这就 ...
- ruby hash排序
参考文章:http://blog.csdn.net/ppp8300885/article/details/49933305 a={a:1,b:20,c:3,d:0,e:7}逆序 a.sort{|k,v ...
- 数据结构之 排序---折半插入排序(时间复杂度 O(nlog2 n) )
排序 Time Limit: 1000MS Memory limit: 32678K 题目描述 给你N(N<=100)个数,请你按照从小到大的顺序输出. 输入 输入数据第一行是一个正整数N,第二 ...