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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM