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

题意

给你一个1~n排列,问有没有一个等差数列(长度至少为3)

题解

我居然自己想到了正解。

但我最后写挂了,所以我又看了题解。

我们维护了一个以权值为下标的01序列。

我们扫描整个序列。对于每一个正在扫描的数,我们判断以这个数的权值作为对称点,01序列是否对称。

这个序列用权值树状数组维护就行。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define LL long long 
 7 const LL mod=1e9+7;
 8 int n,t;
 9 const int N=10010;
10 LL pw[N],c1[N],c2[N];
11 int a[N];
12 int min(int a,int b){
13     if(a<b)return a;
14     else return b;
15 }
16 int lowbit(int x){
17     return x&(-x);
18 }
19 LL check1(int x){
20     LL ans=0;
21     for(int i=x;i>=1;i-=lowbit(i)){
22         ans=(ans+(c1[i]*pw[x-i])%mod)%mod;
23     }
24     return ans;
25 }
26 LL check2(int x){
27     LL ans=0;
28     for(int i=x;i>=1;i-=lowbit(i)){
29         ans=(ans+(c2[i]*pw[x-i])%mod)%mod;
30     }
31     return ans;
32 }
33 LL add1(int x){
34        for(int i=x;i<=n;i+=lowbit(i)){
35            c1[i]=(c1[i]+pw[i-x])%mod;
36     }
37 }
38 LL add2(int x){
39     for(int i=x;i<=n;i+=lowbit(i)){
40         c2[i]=(c2[i]+pw[i-x])%mod;
41     }
42     return 0;
43 }
44 LL query1(int l,int r){
45     LL p=check1(l-1),q=check1(r);
46     return ((q-p*pw[r-l+1])%mod+mod)%mod;
47 }
48 LL query2(int l,int r){
49     LL p=check2(l-1),q=check2(r);
50     return ((q-p*pw[r-l+1])%mod+mod)%mod;
51 }
52 int main(){
53     scanf("%d",&t);
54     pw[0]=1;
55     for(int i=1;i<=10001;i++)pw[i]=(pw[i-1]*(LL)2)%mod;
56        for(int z=1;z<=t;z++){
57         scanf("%d",&n);
58         for(int i=1;i<=n;i++)scanf("%d",&a[i]);
59         memset(c1,0,sizeof(c1));memset(c2,0,sizeof(c2));
60         for(int i=1;i<=n;i++){
61             int x=a[i];
62             int len=min(n-x,x-1);
63             if(len&&query1(x-len,x-1)!=query2(n-x-len+1,n-x)){printf("Y\n");break;}
64             add1(x);add2(n-x+1);
65             if(i==n)printf("N\n");
66         }
67     }
68     return 0;
69 }
View Code

 

转载于:https://www.cnblogs.com/Xu-daxia/p/9402502.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值