bzoj 2124: 等差子序列 树状数组&hash

       这道题太神了根本想不到QAQ。

       题目就是求是否存在i<j<k,使得Ak-Aj=Aj-Ai。

       我们不妨枚举中间那个数为x,然后按照输入的顺序对x进行操作。如果x满足条件,也就是存在两个数y和z,x-y=z-x,并且y已经出现过了而z还没有出现,那么我们就可以直接输出'Y'了。

       因此,我们构造一个辅助数组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值即可。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define mod 1000000007
#define N 10005
using namespace std;

int n,a[N],pw[N];
struct bit_node{
	int c[N];
	void clr(){ memset(c,0,sizeof(c)); }
	void add(int x){
		int i; for (i=x; i<=n; i+=i&-i) c[i]=(c[i]+pw[i-x])%mod;
	}
	int getsum(int x){
		int i,t=0; for (i=x; i; i^=i&-i) t=((ll)c[i]*pw[x-i]+t)%mod;
		return t;
	}
	int qry(int x,int y){
		int p=getsum(x-1),q=getsum(y);
		return (q-(ll)p*pw[y-x+1]%mod+mod)%mod;
	}
}bit1,bit2;
int main(){
	int cas,i; scanf("%d",&cas);
	pw[0]=1; for (i=1; i<=10000; i++) pw[i]=(ll)pw[i-1]*12347%mod;
	while (cas--){
		scanf("%d",&n); int x;
		for (i=1; i<=n; i++) scanf("%d",&a[i]);
		bit1.clr(); bit2.clr();
		for (i=1; i<=n; i++){
			x=min(a[i]-1,n-a[i]);
			if (x && bit1.qry(a[i]-x,a[i]-1)!=bit2.qry(n-a[i]-x+1,n-a[i])) break;
			bit1.add(a[i]); bit2.add(n-a[i]+1);
		}
		puts((i>n)?"N":"Y");
	}
	return 0;
}


by lych

2016.5.12

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值