等差子序列 bzoj-2124

题目大意:给定一个1~n的排列,问是否存在3个及以上的位置上的数构成连续的等差子序列。

注释:$1\le n\le 10^4$。

想法:这题就相当于是否存在3个数i,j,k,a[i]表示i位置上的数,使得:i<j<k且a[k]-a[j]=a[j]-a[i]。

引理1:一个满足条件的序列,一定是x-a,x,x+a的形式。

证明:滚。

引理2:两个数x和y,如果y不在x之前出现,那么y一定在x之后出现。

证明:因为是1~n的排列,所以y必然出现,证毕。

引理3:如果存在2个数,x出现了,y出现了,2*y-x没出现,那么一定存在满足条件的解。

证明:由引理2,显然。

那么,我们对于当前桶维护权值线段树,此时:假设当前指针p在(n+1)>>1左侧,如果1~2*p-1在桶上构成的01字符串不是关于p回文的(此处p处桶已经存在),那么说明两个位置关于p对称且一个为1,一个为0。那么,为0的位置有引理3必定会在之后的某一个位置出现,这是一定是存在满足条件的序列的。换句话说,我们只需要判断每次枚举到的数在桶上的位置左右在长度极大的情况下是不是关于该位置回文的。这时,我们只需要对于桶内的每一个点维护向前、向后的hash前(后)缀和,O(1)判断即可。那么,我们如何更新呢?我们发现,当前位置有0变成1,只会使得小于这个数的后缀和和大于这个数的前缀和的hash值发生变化。那,变化了多少呢?假设当前位置是p,hash的增量是base,显然后面的数每个位置的hash值都会增加$base^{p-1}$,前面的数的后缀和都会增加$base^{n-p}$,而这个过程可以用线段树在log的时间内维护。每次就是区间加,和单点查询,复杂度是O(nlogn)。

最后,附上丑陋的代码... ...

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100010
#define lson pos<<1
#define rson pos<<1|1
using namespace std;
typedef unsigned long long ull;
const ull base=233;
int cases,n,a[N];
ull hash1[N<<2],hash2[N<<2],p[N];
void fix(int pos,int l,int r,int x)
{
if(l==r)
{
hash1[pos]=hash2[pos]=base;
return;
}
int mid=(l+r)>>1;
if(x<=mid) fix(lson,l,mid,x);
else fix(rson,mid+1,r,x);
hash1[pos]=hash1[lson]*p[r-mid]+hash1[rson];
hash2[pos]=hash2[rson]*p[mid-l+1]+hash2[lson];
}
ull gethash(int pos,int l,int r,int x,int y,int v)
{
if(x<=l&&r<=y)
{
if(v==1)return hash1[pos];
return hash2[pos];
}
int mid=(l+r)>>1;
if(y<=mid) return gethash(lson,l,mid,x,y,v);
if(x>mid) return gethash(rson,mid+1,r,x,y,v);
ull lre=gethash(lson,l,mid,x,y,v),rre=gethash(rson,mid+1,r,x,y,v);
if(v==1)return lre*p[min(y,r)-mid]+rre;
return rre*p[mid-max(x,l)+1]+lre;
}
int main()
{
cin >> cases ; p[0]=1;
for(int i=1;i<=10000;i++) p[i]=p[i-1]*base;
while(cases--)
{
memset(hash1,0,sizeof hash1);
memset(hash2,0,sizeof hash2);
memset(a,0,sizeof a);
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
int flag=0;
for(int len,i=1;i<=n;++i)
{
fix(1,1,n,a[i]);
len=min(a[i],n-a[i]+1);
if(gethash(1,1,n,a[i]-len+1,a[i],1)!=gethash(1,1,n,a[i],a[i]+len-1,2))
{
flag=1;
break;
}
}
if(flag)puts("Y");
else puts("N");
}
return 0;
}

小结:线段树真tm牛逼,hash更牛逼... ...

[bzoj2124]等差子序列_线段树_hash的更多相关文章

  1. BZOJ_2124_等差子序列_线段树+Hash

    BZOJ_2124_等差子序列_线段树+Hash Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pL ...

  2. dutacm.club_1094_等差区间_(线段树)(RMQ算法)

    1094: 等差区间 Time Limit:5000/3000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)Total ...

  3. bzoj2124: 等差子序列线段树+hash

    bzoj2124: 等差子序列线段树+hash 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2124 思路 找大于3的等差数列其实就是找等于 ...

  4. [BZOJ2124]等差子序列/[CF452F]Permutation

    [BZOJ2124]等差子序列/[CF452F]Permutation 题目大意: 一个\(1\sim n\)的排列\(A_{1\sim n}\),询问是否存在\(i,j(i<j)\),使得\( ...

  5. BZOJ_2957_楼房重建_线段树

    BZOJ_2957_楼房重建_线段树 Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多 ...

  6. BZOJ_4636_蒟蒻的数列_线段树+动态开点

    BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...

  7. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

  8. BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针

    BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间, ...

  9. BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心

    BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...

随机推荐

  1. bzoj 1026 [ SCOI2009 ] windy数 —— 数位DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1026 蛮简单的数位DP,预处理 f[i][j] 表示 i 位数,以 j 开头的 windy ...

  2. Building a Space Station(bfs)

    http://poj.org/problem?id=2031 题意:给出n个球的圆心坐标x,y,z, 半径r,若任意两球不相交,则在两球间建桥.问需建桥的最短距离是多少. 思路:建图,以两球间相差的距 ...

  3. Shredding Company(dfs)

    http://poj.org/problem?id=1416 题意:将一个数分成几部分,使其分割的各个数的和最大并且小于所给的数. 凌乱了..参考的会神的代码..orz... #include < ...

  4. [Apple开发者帐户帮助]三、创建证书(4)创建Safari签名证书

    您的Safari扩展程序必须由Apple颁发的证书签名,您可以在开发者帐户中创建和下载该证书. 在“ 证书”,“标识符和配置文件”中,从左侧的弹出菜单中选择“Safari扩展”. 在“证书”下,选择“ ...

  5. Python 29 异常处理, 元类

    所学内容 异常处理(常用) AttributeError ··························  试图访问一个对象没有的树形,比如foo.x,但是foo没有属性xIOError ··· ...

  6. Java 中静态变量和实例变量区别

    Java 中静态变量和实例变量区别 静态变量属于类,该类不生产对象,通过类名就可以调用静态变量. 实例变量属于该类的对象,必须产生该类对象,才能调用实例变量. 在程序运行时的区别: 实例变量属于某个对 ...

  7. 大白话理解cookie

    HTTP协议是一个无状态的协议,服务器无法区分出两次请求是否发送自同一服务器. 需要通过会话控制来解决这个问题,会话控制主要有两种方式Cookie 和 Session. Cookie就是一个头,Coo ...

  8. 努比亚(nubia) M2青春版 NX573J 解锁BootLoader 并进入临时recovery ROOT

    努比亚(nubia) M2青春版 NX573J 解锁BootLoader 并进入临时recovery ROOT 工具下载链接:https://pan.baidu.com/s/1NfRTdXtdAZRi ...

  9. Eclipse之注释部分代码

    有时为了调试,部分代码需要注释掉,如果一行一行的加注释符特别麻烦. 一.快捷键:ctrl+/ 选择需要注释的部分,点Ctrl+/,这段代码前,自动加注释语. 取消注释也是按Ctrl+/ 步骤: 选择需 ...

  10. OpenCV:使用 随机森林与GBDT

    随机森林顾名思义,是用随机的方式建立一个森林.简单来说,随机森林就是由多棵CART(Classification And Regression Tree)构成的.对于每棵树,它们使用的训练集是从总的训 ...