题目大意

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

题解

显然,我们只需要找到\(P_1, P_2, P_3\),使得其为等差数列即可。

考察等差数列的定义,不难得出:

\[2*P_2 = P_1 + P_3
\]

考察每一个\(P_2\),如果有\(P_2 - d\)已经出现,\(P_2 + d\)没有出现,那么一定可以组成等差序列。

我们考虑使用线段树维护每一个数字是否出现。如果一个数满足要求,以这个数开头的正序串和逆序串一定是不同的。我们维护每一个区间的哈希值,比较即可。

由于维护时满足区间查询,单点修改,所以我们使用线段树。

这个题WA了八次,最后找root要了数据才发现自己哈希的时候使用的pow数组用了int,结果溢出了orz

代码

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#define ll long long
#define mod 1000000007
#define p 3
using namespace std;
const int maxn = 10005;
struct seg {
int l, r;
ll hash1, hash2;
} t[maxn * 4];
int n, T;
ll pow[maxn];
void update(int k, ll m) {
ll tmp = m >> 1;
t[k].hash1 = ((t[k << 1].hash1 * pow[tmp]) % mod + t[k << 1 | 1].hash1) % mod;
t[k].hash2 =
((t[k << 1 | 1].hash2 * pow[m - tmp]) % mod + t[k << 1].hash2) % mod;
}
void add(int k, int pos) {
int l = t[k].l, r = t[k].r, mid = (l + r) >> 1;
if (l == r) {
t[k].hash1 = t[k].hash2 = 1;
return;
}
if (pos <= mid)
add(k << 1, pos);
else
add(k << 1 | 1, pos);
update(k, r - l + 1);
}
ll query(int k, int x, int y, int opt) {
if (x > y)
return 0;
int l = t[k].l, r = t[k].r, mid = (l + r) >> 1;
if (x <= l && r <= y) {
if (opt == 1)
return t[k].hash1;
else
return t[k].hash2;
}
if (y <= mid)
return query(k << 1, x, y, opt);
else if (x > mid)
return query(k << 1 | 1,x , y, opt);
else {
if (opt == 1) {
return ((query(k << 1, x, mid, 1) * pow[y - mid]) % mod+
query(k << 1 | 1, mid + 1, y, 1) % mod) %
mod;
} else
return ((query(k << 1, x, mid, 2) +
query(k << 1 | 1, mid + 1, y, 2) * pow[mid - x + 1])%mod) %
mod;
}
}
void build(int k, int l, int r) {
t[k].l = l, t[k].r = r;
if (l == r) {
t[k].hash1 = t[k].hash2 = 0;
return;
}
int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
update(k, r - l + 1);
}
int main() {
//freopen("sequence.in", "r", stdin);
//freopen("sequence.out", "w", stdout);
scanf("%d", &T);
//pow[0] = 1;
pow[1] = p;
for (int i = 2; i <= 10001; i++)
pow[i] = (pow[i - 1] * p) % mod;
while (T--) {
scanf("%d", &n);
build(1, 1, n);
//memset(t, 0, sizeof(t));
int flag = 0;
int a[maxn];
memset(a, 0, sizeof(a));
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) {
int x = a[i];
ll len = min(x - 1, n - x);
ll tmp1 = query(1, x - len, x - 1, 1);
ll tmp2 = query(1, x + 1, x + len, 2);
if (tmp1 != tmp2) {
flag = 1;
break;
}
add(1, x);
}
if (flag)
printf("Y\n");
else
printf("N\n");
}
}

[bzoj2124]等差子序列——线段树+字符串哈希的更多相关文章

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

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

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

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

  3. BZOJ2124 等差子序列(树状数组+哈希)

    容易想到一种暴力的做法:枚举中间的位置,设该位置权值为x,如果其两边存在权值关于x对称即合法. 问题是如何快速寻找这个东西是否存在.考虑仅将该位置左边出现的权值标1.那么若在值域上若关于x对称的两权值 ...

  4. [bzoj2124]等差子序列(hash+树状数组)

    我又来更博啦     2124: 等差子序列 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 941  Solved: 348[Submit][Statu ...

  5. BZOJ 2124等差子序列 线段树&&hash

    [题目描述 Description] 给一个 1 到 N 的排列{Ai},询问是否存在 1<=p1<p2<p3<p4<p5<…<pLen<=N(Len& ...

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

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

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

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

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

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

  9. BZOJ2124: 等差子序列(树状数组&hash -> bitset 求是否存在长度为3的等差数列)

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

随机推荐

  1. Appium iOS万能的定位方式--Predicate(iOSNsPredicate)

    所谓Predicate定位即Java-Client -5.0.版本以及Appium-Python-Client 0.31版本更新后增加的新的定位方式: 举个例子: JAVA代码: //输入账号和密码 ...

  2. 孤荷凌寒自学python第七十天学习并实践beautifulsoup对象用法3

    孤荷凌寒自学python第七十天学习并实践beautifulsoup对象用法3 (完整学习过程屏幕记录视频地址在文末) 今天继续学习beautifulsoup对象的属性与方法等内容. 一.今天进一步了 ...

  3. C++ STL容器——stack用法介绍

    stack是一种容器适配器,专门设计用于在LIFO上下文中操作(后进先出),其中元素仅从容器的一端插入和删除. 容器适配器,而不是一种容器. 它是容器适配器是指,只要支持一系列方法的容器(empty, ...

  4. python之*args和**kwargs参数,以及迭代器

    *args让函数可以接受不限制多个位置参数,**kwargs让函数可以接受不限制多个关键字参数,用法如图 2.迭代器总结

  5. BZOJ 4004 JLOI2015 装备购买 高斯消元+线性基

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4004 Description 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装 ...

  6. 软件工程项目组Z.XML会议记录 2013/09/25

    软件工程项目组Z.XML会议记录 [例会时间]2013年9月25日周三21:30-22:10 [例会形式]小组讨论 [例会地点]三号公寓楼会客厅 [例会主持]李孟 [会议记录]肖俊鹏 会议整体流程 签 ...

  7. AndroidStudio3.0 注解报错Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor.

    体验最新版AndroidStudio3.0 Canary 8的时候,发现之前项目的butter knife报错,用到注解的应该都会报错 Error:Execution failed for task ...

  8. mysql yearweek修改开始日期

    MySQL 的yearweek函数默认是从周日~周六,需求需要从周一到周日,看了MySQL的文档后,按照如下使用即可更改开始日期. http://dev.mysql.com/doc/refman/5. ...

  9. (转)String,StringBuffer与StringBuilder的区别??

    String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) 简要的说, String 类型和 StringBuffer 类型的主要性能 ...

  10. 关于<meta http-equiv="Content-Type" content="text/html:charset=UTF-8">

    meta是html的元标签,其中包含了对应html的相关信息,客户端浏览器或服务端程序都会根据这些信息进行处理.我们以<meta http-equiv="Content-Type&qu ...