zoukankan      html  css  js  c++  java
  • loj #6287. 诗歌 哈希+树状数组

    这道题思路很巧妙。

    我们从1到n处理每个数的时候同时维护好桶 (t[])

    当我们处理到 (i) 的时候,我们将 (t[a[i]]) 赋值为 (1)

    如果这时候以 (a[i]) 为中心的 (t) 极大字符串并不是一个回文串,那么就说明存在一个 (j) ,满足(t[a[i]-j]) 不等于 (t[a[i]+j]),也就是 (a[i]-j)(a[i]+j) 分别在 (a[i]) 的两侧,就说明满足题目的要求。

    如何判断回文串?用树状数组维护哈希就行了。

    时间复杂度 (O(nlogn))

    #include<iostream>
    #include<cstdio>
    #define ULL unsigned long long
    using namespace std;
    int n;
    const int N=300010;
    int a[N];
    ULL b[N];
    struct SZSZ
    {
    	ULL tr[N];
    	int lowbit(int x){return x&(-x);}
    	void add(int pos,ULL val)
    	{
    		for(;pos<=n;pos+=lowbit(pos))tr[pos]+=val;
    	}
    	ULL ask(int pos)
    	{
    		ULL res=0;
    		for(;pos;pos-=lowbit(pos))res+=tr[pos];
    		return res;
    	}
    }A,B;
    int check(int x)
    {
    	int len=min(x,n-x+1);
    	ULL u=A.ask(x)-A.ask(x-len),v=B.ask(x+len-1)-B.ask(x-1);
    	A.add(x,b[x]);B.add(x,b[n-x+1]);
    	return u*b[n-x-len+2]!=v*b[x-len+1];
    }
    int main()
    {
    	cin>>n;b[0]=1;
    	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    	for(int i=1;i<=n;++i)b[i]=b[i-1]*131;
    	for(int i=1;i<=n;++i)
    		if(check(a[i]))return puts("YES")==2333;
    	puts("NO");
    	return 0;
    }
    
  • 相关阅读:
    高级打字机
    不等数列
    间谍网络
    医院设置
    题目编号生成器
    传纸条
    聪明的打字员
    倒水问题
    八数码难题
    生日蛋糕
  • 原文地址:https://www.cnblogs.com/wljss/p/13371016.html
Copyright © 2011-2022 走看看