[bzoj2124]等差子序列——线段树+字符串哈希
题目大意
给一个1到N的排列\(A_i\),询问是否存在\(p_i\),\(i>=3\),使得\(A_{p_1}, A_{p_2}, ... ,A_{p_len}\)是一个等差序列。
题解
显然,我们只需要找到\(P_1, P_2, 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]等差子序列——线段树+字符串哈希的更多相关文章
- bzoj2124: 等差子序列线段树+hash
bzoj2124: 等差子序列线段树+hash 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2124 思路 找大于3的等差数列其实就是找等于 ...
- BZOJ2124:等差子序列(线段树,hash)
Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3), 使得A ...
- BZOJ2124 等差子序列(树状数组+哈希)
容易想到一种暴力的做法:枚举中间的位置,设该位置权值为x,如果其两边存在权值关于x对称即合法. 问题是如何快速寻找这个东西是否存在.考虑仅将该位置左边出现的权值标1.那么若在值域上若关于x对称的两权值 ...
- [bzoj2124]等差子序列(hash+树状数组)
我又来更博啦 2124: 等差子序列 Time Limit: 3 Sec Memory Limit: 259 MBSubmit: 941 Solved: 348[Submit][Statu ...
- BZOJ 2124等差子序列 线段树&&hash
[题目描述 Description] 给一个 1 到 N 的排列{Ai},询问是否存在 1<=p1<p2<p3<p4<p5<…<pLen<=N(Len& ...
- bzoj 2124 等差子序列 (线段树维护hash)
2124: 等差子序列 Time Limit: 3 Sec Memory Limit: 259 MBSubmit: 1922 Solved: 714[Submit][Status][Discuss ...
- BZOJ 2124: 等差子序列 线段树维护hash
2124: 等差子序列 Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一 ...
- CF452F等差子序列 & 线段树+hash查询区间是否为回文串
记录一下一个新学的线段树基础trick(真就小学生trick呗) 给你一个1到n的排列,你需要判断该排列内部是否存在一个3个元素的子序列(可以不连续),使得这个子序列是等差序列.\(n\) <= ...
- BZOJ2124: 等差子序列(树状数组&hash -> bitset 求是否存在长度为3的等差数列)
2124: 等差子序列 Time Limit: 3 Sec Memory Limit: 259 MBSubmit: 2354 Solved: 826[Submit][Status][Discuss ...
随机推荐
- jmeter对请求参数的签名处理
1.首先在本地写好签名的算法,本文采用RSA签名. public final class Base64 { static private final int BASELENGTH = 128; sta ...
- 2.Linux文件和目录
1. 目录和路径 linux下比较特殊的目录: . 代表此层目录 .. 代表上一层目录 - 代表前一个工作目录 ~ 代表『目前使用者身份』所在的home目录 ~account 代表 account 这 ...
- Linux编译安装opencv
参考https://blog.csdn.net/huang826336127/article/details/78760885 一.下载opencv源码包 下载地址:https://opencv.or ...
- Python中enumerate函数用法详解
enumerate函数用于遍历序列中的元素以及它们的下标,多用于在for循环中得到计数,enumerate参数为可遍历的变量,如 字符串,列表等 一般情况下对一个列表或数组既要遍历索引又要遍历元素时, ...
- 集显也能硬件编码:Intel SDK && 各种音视频编解码学习详解
http://blog.sina.com.cn/s/blog_4155bb1d0100soq9.html INTEL MEDIA SDK是INTEL推出的基于其内建显示核心的编解码技术,我们在播放高清 ...
- js调用本地office打开服务器的office文件预览
本来是想做成直接在网页上在线预览office文件的,但是找了好多,要不是收费,要不就是要调用别人的API不安全,所以纠结了好久还是用调用本地的office预览office文件. 废话不多说,那么怎么调 ...
- PokeCats开发者日志(三)
现在是PokeCats游戏开发的第四天的晚上,明天要过周末了,所以提前写一下开发者日志吧! day4 day4主要是优化界面和增加游戏可玩性. (1)感觉只有三只喵喵的话,玩家只需要无脑点 ...
- Java基础知识-去重
java基础知识-去掉list集合中的重复元素: 思路: 首先新建一个容器resultList用来存放去重之后的元素 然后遍历sourceList集合中的元素 判断所遍历的元素是否已经存在于resul ...
- ArcGis下的叠加分析
1矢量与矢量叠加的话就用ToolBox里有Overlay: 2如果是矢量和栅格叠加的话用Spatial analysis模块中的 zonal statistics: 3还有就是栅格与栅格的叠加S ...
- 使用XML传递数据
HTML <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...