【题目描述 Description】

给一个 1 到 N 的排列{Ai},询问是否存在 1<=p1<p2<p3<p4<p5<…<pLen<=N(Len>=3),使得 Ap1,Ap2,Ap3,…ApLen 是一个等差序列。

【输入描述 Input Description】

输入的第一行包含一个整数 T,表示组数。

下接 T 组数据,每组第一行一个整数 N,每组第二行为一个 1 到 N 的排列, 数字两两之间用空格隔开。

【输出描述 Output Description】

对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则输出一 行“N”。

【样例输入 Sample Input】

2

3

1 3 2

3

3 2 1

【样例输出 Sample Output】

N

Y

【数据范围及提示 Data Size & Hint】

对于5%的数据,N<=100,对于30%的数据,N<=1000,对于100%的数据,N<=10000,T<=7

【解题思路】

首先声明,此题开始并没有什么思路,只找到一个O(N^2)的算法,然而这并没有什么卵用。

老师明示暗示我要我用线段树去做,我苦思冥想没有想出来,于是就抄了题解。

题解是这样的,枚举等差中项,用一颗线段树去维护那些值选了,那些值没选,构成一个01串之后求一个哈希值。

如果出现中项左边的hash值和右边的hash值不一样的情况,就说明存在等差数列,因为证明有一个值在中项左边已经选过,并且与其对应的值在中项右边还没有选。

插入O(logn),查询O(logn),扫一遍O(n)整体O(ologn);

代码略丑

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=+, mod=;
int xp[maxn],a[maxn],n,v,t;
long long sumv[*maxn][];
//sumv[i][0] 代表从左边扫的值,sumv[i][1]代表从右边扫的值
void updata(int u,int l,int r){
int lc=u<<,rc=lc+;
if (l==r) sumv[u][]=sumv[u][]=;
else{
int mid=(l+r)/;
if (v<=mid) updata(lc,l,mid);
else updata(rc,mid+,r);
sumv[u][]=(sumv[rc][]+xp[r-mid]*sumv[lc][]%mod)%mod;
sumv[u][]=(sumv[lc][]+xp[mid-l+]*sumv[rc][]%mod)%mod;
}
} long long query(int node,int l,int r,int a,int b,int x){
int lc=node<<,rc=lc+;
if (l==a&&r==b) return sumv[node][x];
int mid=(l+r)/;
long long left=,right=;
if (mid<b) right=query(rc,mid+,r,max(mid+,a),b,x);
if (a<=mid) left=query(lc,l,mid,a,min(mid,b),x);
return (x?left+right*xp[max(,mid-a+)]%mod:right+left*xp[max(,b-mid)]%mod)%mod;
} int main(){
scanf("%d",&t);
for (int ii=;ii<t;ii++){
memset(sumv,,sizeof(sumv));
bool flag=;
scanf("%d",&n);
xp[]=;
for (int i=;i<=n+;i++) xp[i]=(xp[i-]<<)%mod;
for (int i=;i<n;i++)scanf("%d",&a[i]);
for (int i=;i<n;i++){
int x=a[i];
int len=min(x-,n-x);//长度取短之后比较
if (len) {
int t1=query(,,n,x+,x+len,);
int t2=query(,,n,x-len,x-,);
if (t1!=t2){
flag=;
break;
}
}
v=x;
updata(,,n);
}
if (flag) printf("Y\n");
else printf("N\n");
}
}

以上为堆状线段树,由于我一直喜欢用结构体,所以就又打了一个,然后发现内存时间代码复杂度都比堆要差,大概是因为要建树和结构体太大的缘故。线段树的种类的确要视题目而定。

 #include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=+,mod=;
struct tree{
int l,r,lch,rch;
long long sum;
}tr[maxn*][];
//tr[now][0]代表从左往右, tr[now][1]代表从右往左
int cnt,n,t,xp[maxn],a[maxn]; void build(int now,int l,int r){
cnt++;
tr[cnt][].l=tr[cnt][].l=l; tr[cnt][].r=tr[cnt][].r=r;
if (l==r) return;
tr[cnt][].lch=tr[cnt][].lch=cnt+;
int mid=(l+r)>>;
build(cnt+,l,mid);
tr[now][].rch=tr[now][].rch=cnt+;
build(cnt+,mid+,r);
} long long query(int now,int l,int r,int x){
long long t1=,t2=;
if (tr[now][x].l==l&&tr[now][x].r==r) return tr[now][x].sum;
int mid=(tr[now][x].l+tr[now][x].r)>>;
if (l<=mid) t1=query(tr[now][x].lch,l,min(r,mid),x)%mod;
if (r>mid) t2=query(tr[now][x].rch,max(mid+,l),r,x)%mod;
if (x==) return ((t1*xp[max(,r-mid)])%mod+t2)%mod;
if (x==) return ((t2*xp[max(mid-l+,)])%mod+t1)%mod;
//返回值的时候*xp的时候错过,乘的是数目,虽然我不知道我刚开始为什么写的不对
} void insert(int now,int x){
if (tr[now][].l==x&&tr[now][].r==x){
tr[now][].sum=tr[now][].sum=;
return;
}
int mid=(tr[now][].l+tr[now][].r)>>;
if (x<=mid) insert(tr[now][].lch,x);
if (x>=mid+) insert(tr[now][].rch,x);
int l=tr[now][].l,r=tr[now][].r;
tr[now][].sum=((tr[tr[now][].lch][].sum*xp[r-mid])%mod
+tr[tr[now][].rch][].sum)%mod;
tr[now][].sum=((tr[tr[now][].rch][].sum*xp[mid-l+])%mod
+tr[tr[now][].lch][].sum)%mod;
} int main(){
scanf("%d",&t);
while (t--){
memset(tr,,sizeof(tr));
cnt=;//开始忘记清零CE了
scanf("%d",&n);
xp[]=;
bool flag=;
for (int i=;i<=n+;i++) xp[i]=(xp[i-]<<)%mod;//预处理出所有二的幂
build(,,n);
for (int i=;i<n;i++) scanf("%d",&a[i]);
for (int i=;i<n;i++){
int x=a[i];
int len=min(a[i]-,n-a[i]);
if (len&&query(,x-len,x-,)!=query(,x+,x+len,)){
flag=;
break;
}
insert(,x);
}
if (flag) printf("Y\n");
else printf("N\n");
}
}

BZOJ 2124等差子序列 线段树&&hash的更多相关文章

  1. bzoj 2124 等差子序列 (线段树维护hash)

    2124: 等差子序列 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 1922  Solved: 714[Submit][Status][Discuss ...

  2. BZOJ 2124: 等差子序列 线段树维护hash

    2124: 等差子序列 Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一 ...

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

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

  4. BZOJ2124:等差子序列(线段树,hash)

    Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3), 使得A ...

  5. CF452F等差子序列 & 线段树+hash查询区间是否为回文串

    记录一下一个新学的线段树基础trick(真就小学生trick呗) 给你一个1到n的排列,你需要判断该排列内部是否存在一个3个元素的子序列(可以不连续),使得这个子序列是等差序列.\(n\) <= ...

  6. BZOJ 2124: 等差子序列

    Sol 线段树+Hash. 首先暴力 等差子序列至少3项就可以了,就枚举中项,枚举公差就可以了,只需要一个数在中项前出现,另一个数在中项前没出现过就可以了.复杂度 \(O(n^2)\) 然后我想了一个 ...

  7. bzoj 2124 等差子序列 树状数组维护hash+回文串

    等差子序列 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 1919  Solved: 713[Submit][Status][Discuss] Desc ...

  8. [bzoj2124]等差子序列——线段树+字符串哈希

    题目大意 给一个1到N的排列\(A_i\),询问是否存在\(p_i\),\(i>=3\),使得\(A_{p_1}, A_{p_2}, ... ,A_{p_len}\)是一个等差序列. 题解 显然 ...

  9. bzoj 3207 可持久化线段树+hash

    这道题要看出来这个做法还是比较容易说一下细节 1.因为要用hash的区间值域来建树,而hash为了不冲突要开的很大,所以值域就会比较的大,不过这道题好的一点是没有修改,所以直接离散一下就会小很多 2. ...

随机推荐

  1. C#数据操作LINQ

    Linq是language integrated query的缩写,即"语言集成查询"之意. Linq主要包含四个组件,Linq to object.Linq to XML.Lin ...

  2. Storyboards vs NIB vs Code 大辩论

    前言 做iOS开发的童鞋都应该会纠结一个问题,那就是在做开发的时候是使用StoryBoard还是使用Nibs又或者是Code(纯代码流)呢?笔者也非常纠结这个问题,今天碰巧在raywenderlich ...

  3. Java基础知识强化之网络编程笔记19:Android网络通信之 HttpClient和传统Post、Get方式的区别

    1. HttpClient是什么 ?     HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源.虽然在 ...

  4. APP运营干货分享

    从移动互联网市场总监岗位出发,从几个方面来阐述移动互联网部门如何制定一份运营推广策划案,至于关于移动互联网,移动电商是大趋势这些虚的.空泛的文字,不展开说了. 一.竞品分析 1.选择竞品,做好定位(选 ...

  5. ubuntu 安装sublime并激活

    1:add-apt-repository ppa:webupd8team/sublime-text-3加载sublime的源2:sudo apt-get update更新源 3:sudo apt-ge ...

  6. Python基础:1.数据类型(空、布尔类型、整型、长整型、浮点型、字符串)

    提示:python版本2.7,windows系统 Python提供的基本数据类型:空.布尔类型.整型.长整型.浮点型.字符串.列表.元组.字典.日期 1.空(None) None,是一个特殊的值,不能 ...

  7. VSPackge插件系列:常用IDE功能的封装

    继上一篇VSPackge插件系列简单介绍如何正确的获取DTE之后,就一直没发VSPackge插件系列的文章了,最近同事也想了解如何在代码中与VS交互,特发一篇文章示例一些简单功能是如何调用,也以备以后 ...

  8. 【总结】教你怎么将centos7打造成桌面系统

    http://tieba.baidu.com/p/3379447850 centos吧

  9. SharePoint缓存导致访问慢解决

    产品发布到公网时,客户每次访问页面都很慢,经过查找原因,发现在服务器上的APPFabric缓存出错误了: APPFabric缓存服务作用:用作内存中缓存来存储应用程序访问的数据,从而提高应用程序性能. ...

  10. Session对象的集合

    Session StaticObjects 集合 StaticObjects 集合包含 Session 对象范围中用 <OBJECT> 标记创建的所有对象.该集合可用于确定对象特定属性的值 ...