BZOJ2124 等差子序列

来源:互联网 发布:志鸿优化设计历史答案 编辑:程序博客网 时间:2024/06/06 00:42

挺厉害的题

我们考虑当前加入了第i个数,为x,那么我们可以维护一下哪个数出现过,出现过为1,没出现为0,那么加入x的时候我们只需要判断以x为中心的极长子串是否是回文串即可

用一个树状数组维护两个方向的哈希值即可

#include<iostream>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<cstdlib>#include<cstdio>#include<map>#include<bitset>#include<set>#include<stack>#include<vector>#include<queue>using namespace std;#define MAXN 10010#define MAXM 1010#define ll long long#define eps 1e-8#define MOD 1000000007#define INF 1000000000#define lb(x) x&-xint n;int x;ll c1[MAXN],c2[MAXN];ll bas=131;ll mi[MAXN];void change(ll *c,int x,ll cv){for(;x<=n;x+=lb(x)){(c[x]+=cv)%=MOD;}}ll ask(ll *c,int x){ll re=0;for(;x;x-=lb(x)){(re+=c[x])%=MOD;}return re;}int main(){int i;int tmp;scanf("%d",&tmp);mi[0]=1;for(i=1;i<MAXN;i++){mi[i]=mi[i-1]*bas%MOD;}while(tmp--){memset(c1,0,sizeof(c1));memset(c2,0,sizeof(c2));bool flag=0;scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&x);change(c1,x,mi[x]);change(c2,n-x+1,mi[n-x+1]);int len1=x,len2=n-x+1;if(len1<=len2){ll h1=ask(c1,len1)*mi[len2-len1]%MOD;ll h2=(ask(c2,len2)-ask(c2,len2-len1)+MOD)%MOD;if(h1!=h2){flag=1;}}else{ll h1=(ask(c1,len1)-ask(c1,len1-len2)+MOD)%MOD;ll h2=ask(c2,len2)*mi[len1-len2]%MOD;if(h1!=h2){flag=1;}}}printf(flag?"Y\n":"N\n");}return 0;}/**/


0 0
原创粉丝点击