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

等差子序列

Time Limit: 3 Sec  Memory Limit: 259 MB
Submit: 1919  Solved: 713
[Submit][Status][Discuss]

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”,否则输出一行“N”。

Sample Input

2
3
1 3 2
3
3 2 1

Sample Output

N
Y

HINT

因此,我们构造一个辅助数组b,其中x如果出现过,那么b[x]=1;否则b[x]=0。因此如果x满足条件,那么必然存在一个数y使得b[x-y]!=b[x+y];然后我们发现如果把b看成一个字符串,那么实际上就是判断以x为中心的极长字符串是否是回文串,如果不是那么显然存在y使得b[x-y]!=b[x+y],那么就可以输出‘Y‘。快速的字符串比较不妨使用hash,然后因为需要修改那么就用两个树状数组分别维护它所在区间正着和倒着的hash值即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define ll long long
 5 #define mod 1000000007
 6 #define N 10005
 7 using namespace std;
 8
 9 int n,a[N],pw[N];
10 struct bit_node{
11     int c[N];
12     void clr(){ memset(c,0,sizeof(c)); }
13     void add(int x){
14         int i; for (i=x; i<=n; i+=i&-i) c[i]=(c[i]+pw[i-x])%mod;
15     }
16     int getsum(int x){
17         int i,t=0; for (i=x; i; i^=i&-i) t=((ll)c[i]*pw[x-i]+t)%mod;
18         return t;
19     }
20     int qry(int x,int y){
21         int p=getsum(x-1),q=getsum(y);
22         return (q-(ll)p*pw[y-x+1]%mod+mod)%mod;
23     }
24 }bit1,bit2;
25 int main(){
26     int cas,i; scanf("%d",&cas);
27     pw[0]=1; for (i=1; i<=10000; i++) pw[i]=(ll)pw[i-1]*12347%mod;
28     while (cas--){
29         scanf("%d",&n); int x;
30         for (i=1; i<=n; i++) scanf("%d",&a[i]);
31         bit1.clr(); bit2.clr();
32         for (i=1; i<=n; i++){
33             x=min(a[i]-1,n-a[i]);
34             if (x && bit1.qry(a[i]-x,a[i]-1)!=bit2.qry(n-a[i]-x+1,n-a[i])) break;
35             bit1.add(a[i]); bit2.add(n-a[i]+1);
36         }
37         puts((i>n)?"N":"Y");
38     }
39 }

原文地址:https://www.cnblogs.com/fengzhiyuan/p/8847699.html

时间: 2024-10-29 15:16:26

bzoj 2124 等差子序列 树状数组维护hash+回文串的相关文章

CF452F Permutations/Luogu2757 等差子序列 树状数组、Hash

传送门--Luogu 传送门--Codeforces 这种题目还能跟哈希扯上关系也是很神了-- 如果存在长度\(>3\)的等差子序列,那么一定存在长度\(=3\)的等差子序列,所以我们只需要找长度为\(3\)的等差子序列.可以枚举等差子序列的第二个元素\(b\),那么存在长度为\(3\)的等差子序列等价于:可以在\(b\)左边找到一个元素\(a\),在\(b\)右边找到一个元素\(c\),满足\(b - a = c - b\). 对于找到\(ac\)两个元素,一个比较直观的想法是:对\(b\)左

ACdreamoj 1011(树状数组维护字符串hash前缀和)

题目链接:http://acdream.info/problem? pid=1019 题意:两种操作,第一种将字符串某个位置的字符换为还有一个字符.另外一种查询某个连续子序列是否是回文串: 解法:有两种hash的办法,所以写了两种解法;首先hash是x1 * p^1+ x2*p^2 +x3*p^3...能够用树状数组维护前缀和,维护两个串,一个是正串.还有一个是反串用于比較.比較时候乘以对应的p倍数推断是否相等. 刘汝佳白书上的hash方法处理这道题更复杂:改动i会对后缀j产生的影响为a*p^(

HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5869 问你l~r之间的连续序列的gcd种类. 首先固定右端点,预处理gcd不同尽量靠右的位置(此时gcd种类不超过loga[i]种). 预处理gcd如下代码,感觉真的有点巧妙... 1 for(int i = 1; i <= n; ++i) { 2 int x = a[i], y = i; 3 for(int j = 0; j < ans[i - 1].size(); ++j) { 4 int g

2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ&#39;s Salesman 【离散化+树状数组维护区间最大值】

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 919    Accepted Submission(s): 290 Problem Description YJJ is a salesman who h

Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2) C. Fountains 【树状数组维护区间最大值】

题目传送门:http://codeforces.com/contest/799/problem/C C. Fountains time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Arkady plays Gardenscapes a lot. Arkady wants to build two new fountains. The

Codeforces1076E. Vasya and a Tree(dfs+离线+树状数组维护)

题目链接:传送门 题目: E. Vasya and a Tree time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Vasya has a tree consisting of n vertices with root in vertex 1. At first all vertices has 0 written on it.

树状数组维护前缀和

树状数组是用来维护序列前缀和的数据结构.它的修改与求和都是O(logn)的,效率非常高. 我们设序列为A,则树状数组c中,c[i]记录序列A的区间[ i-lowbit(i)+1 , i ]中所有数的和. (树状数组是个好东西ovo)  树状数组在进行区间操作时,要从上到下访问,进行单点操作时,要从下到上访问.  树状数组维护序列前缀和的模版如下: #include <iostream> #include <cstdio> #define maxn 500005 using name

Codeforces Round #629 (Div. 3) F - Make k Equal (离散化 树状数组维护前缀和)

https://codeforces.com/contest/1328/problem/F 首先把a数组处理成pair对(num,cnt),表示数字num有cnt个,然后按num升序排序离散化一下. 对于一个数x,若想使得小于x的数字都变成x,必须先把所有小于x的数变成x-1,然后再+1变成x. 同理,要使得大于x的数变成x,必须把所有大于x的数字变成x+1,然后再-1变成x. 以上是题意所要求的必须操作. 思路: 1. 用f[i]数组记录离散化后前i大的数字的总数,那么对于任意第i大数字,可以

树状数组维护前缀和、后缀和、个数|牛牛的Link Power

思路 另线段树做法:https://www.cnblogs.com/fisherss/p/12287606.html F题树状数组维护前缀即可 题目地址 https://ac.nowcoder.com/acm/contest/3004/F #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5+100; int n; char s[maxn]; const ll mod =