bzoj2124: 等差子序列 Hash+线段树

题面:

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

题解:

http://www.cnblogs.com/zyfzyf/p/3898065.html

代码:

#include<bits/stdc++.h>
#define N (1<<15)
#define M (l+r>>1)
#define P (k<<1)
#define S (k<<1|1)
#define K l,r,k
#define L l,M,P
#define R M+1,r,S
#define Z int l=0,int r=n,int k=1
using namespace std;
int n;
typedef unsigned long long ull;
const ull base=23;
ull d[N],u[N],v[N];
void update(Z){
	u[k]=u[P]+u[S]*d[M-l+1];
	v[k]=v[S]+v[P]*d[r-M];
}
void A(int s,int t,Z){
	if(l==r)
		u[k]=v[k]=s;
	else{
		if(t<=M)
			A(s,t,L);
		else
			A(s,t,R);
		update(K);
	}
}
ull Q1(int s,int t,Z){
	return s==l&&t==r?u[k]
	:t<=M?Q1(s,t,L)
	:s>M?Q1(s,t,R)
	:Q1(s,M,L)
	+Q1(M+1,t,R)*d[M-s+1];
}
ull Q2(int s,int t,Z){
	return s==l&&t==r?v[k]
	:t<=M?Q2(s,t,L)
	:s>M?Q2(s,t,R)
	:Q2(M+1,t,R)
	+Q2(s,M,L)*d[t-M];
}
bool check(){
	memset(u,0,sizeof u);
	memset(v,0,sizeof v);
	static int a[N];
	for(int i=0;i!=n;++i)
		scanf("%d",a+i);
	for(int i=0;i!=n;++i){
		if(int k=min(
		a[i]-1,n-a[i]))
			if(Q2(a[i]-k,a[i]-1)
			 !=Q1(a[i]+1,a[i]+k))
				return 1;
		A(1,a[i]);
	}
	return 0;
}
int main(){
	d[0]=1;
	for(int i=1;i!=N;++i)
		d[i]=d[i-1]*base;
	int q;
	for(scanf("%d",&q);q;--q){
		scanf("%d",&n);
		puts(check()?"Y":"N");
	}
}

  

时间: 2024-09-30 10:12:48

bzoj2124: 等差子序列 Hash+线段树的相关文章

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

Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3), 使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一个整数T,表示组数. 下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开. N<=10000,T<=7 Output 对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则

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

我又来更博啦 2124: 等差子序列 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 941  Solved: 348[Submit][Status][Discuss] Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一个整数T,表示组数.下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开. O

bzoj2124 等差子序列(hash+线段树)

2124: 等差子序列 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 719  Solved: 261[Submit][Status][Discuss] Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一个整数T,表示组数.下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开. Output 对

POJ 2528 Mayor&#39;s posters (hash+线段树成段更新)

题意:有一面墙,被等分为1QW份,一份的宽度为一个单位宽度.现在往墙上贴N张海报,每张海报的宽度是任意的,但是必定是单位宽度的整数倍,且<=1QW.后贴的海报若与先贴的海报有交集,后贴的海报必定会全部或局部覆盖先贴的海报.现在给出每张海报所贴的位置(左端位置和右端位置),问张贴完N张海报后,还能看见多少张海报?(PS:看见一部分也算看到.) 思路:简单的成段更新,但是数据量是1千万,会MT,所以要区间压缩(离散化),保证覆盖的关系不变,离散化的时候有个易错的细节,poj数据水了,这个易错点引用h

bnu36907 Subpalindromes 字符串hash+线段树

bnu36907 Subpalindromes 字符串hash+线段树 题意:给一个字符串(<=1e5), 进行操作和查询(<=1e5). 1)将指定位置的字符改为c 2)询问l-r的子串,是否是回文串. 解法 :区间维护pl和pr,表示从左到右的hash和从右到左的hash,然后在up和query中合并区间,最后判断pl和pr是否相等即可. #include <cstdio> #include <ctime> #include <cstdlib> #inc

HDU 1025-Constructing Roads In JGShining&#39;s Kingdom(最长不降子序列,线段树优化)

分析: 最长不降子序列,n很大o(n^2)肯定超,想到了小明序列那个题用线段树维护前面的最大值即可 该题也可用二分搜索来做. 注意问题输出时的坑,路复数后加s #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vecto

HDU - 3973 AC&#39;s String(Hash+线段树)

http://acm.hdu.edu.cn/showproblem.php?pid=3973 题意 给一个词典和一个主串.有两种操作,查询主串某个区间,问这主串区间中包含多少词典中的词语.修改主串某一位置的字符. 分析 题目要求区间查询,和单点更新,那么最先想到的应该是线段树.可字符串怎么利用线段树呢?用hash!首先将词典按规则hash后放入map,然后将主串的hash值放置入线段树中.问题来了,怎么更新结点的hash值呢?假如现在我们知道了s[l...mid]和s[mid+1...r]的ha

Bzoj2124 等差子序列

Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 911  Solved: 337 Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一个整数T,表示组数.下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开. Output 对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则输出一行“N”.

BZOJ 3904 最长上升子序列 lkids 线段树

题目大意:给定一个序列,求以较小数开始的锯齿子序列,使相邻两项之间差值不小于k 令f[i][0]表示第i个数为序列中的较大值的最长子序列 f[i][1]表示第i个数为序列中的较小值的最长子序列 暴力转移是O(n^2)的 我们发现决策点的值都是连续的一段区间 因此用线段树维护一下就行了 (真简略) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #def