《瘟疫傳說:無罪》《貪婪之秋》Steam國區價格調整
阿新 • • 發佈:2021-07-09
這道題思路很巧妙。
我們從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; }