LOJ 6287 诗歌 题解
xiaoh 2020-9-8
题意
给定的排列。若,且,输出YES
,否则输出NO
数据范围
题解
毒瘤联测题
首先,考虑使用。顺序扫描整个序列,当出现在当前位置的左边时,,否则。则对于当前值,对于任意的和必须相等,否则取这一对即可满足条件。用正序和倒序两个树状数组维护函数,然后每个位置查询左侧和右侧是否回文即可。复杂度。
Code
#include<bits/stdc++.h>
using namespace std;
const int PP=13331;
const int MO=998244353;
const int maxN=300000+5;
int a[maxN];
long long P[maxN];
struct SegTree
{
long long d;
}t1[maxN<<2],t2[maxN<<2];
int n,res1,res2;
void pushup1(int u,int l,int r)
{
int m=(l+r)>>1;
t1[u].d=(t1[u<<1].d*P[r-m]%MO+t1[u<<1|1].d)%MO;
}
void pushup2(int u,int l,int r)
{
int m=(l+r)>>1;
t2[u].d=(t2[u<<1|1].d*P[m-l+1]%MO+t2[u<<1].d)%MO;
}
void build2(int u,int l,int r)
{
if (l==r)
{
t2[u].d=1; return;
}
int m=(l+r)>>1;
build2(u<<1|1,m+1,r); build2(u<<1,l,m);
pushup2(u,l,r);
}
void update1(int u,int l,int r,int x)
{
if (l==r)
{
t1[u].d=1; return;
}
int m=(l+r)>>1;
if (x<=m) update1(u<<1,l,m,x);
else update1(u<<1|1,m+1,r,x);
pushup1(u,l,r);
}
void update2(int u,int l,int r,int x)
{
if (l==r)
{
t2[u].d=1; return;
}
int m=(l+r)>>1;
if (x>m) update2(u<<1|1,m+1,r,x);
else update2(u<<1,l,m,x);
pushup2(u,l,r);
}
void query1(int u,int l,int r,int ql,int qr)
{
if (ql<=l && r<=qr)
{
res1=(res1+t1[u].d*P[qr-r]%MO)%MO;
return;
}
int m=(l+r)>>1;
if (ql<=m) query1(u<<1,l,m,ql,qr);
if (qr>m) query1(u<<1|1,m+1,r,ql,qr);
}
void query2(int u,int l,int r,int ql,int qr)
{
if (ql<=l && r<=qr)
{
res2=(res2+t2[u].d*P[l-ql]%MO)%MO;
return;
}
int m=(l+r)>>1;
if (qr>m) query2(u<<1|1,m+1,r,ql,qr);
if (ql<=m) query2(u<<1,l,m,ql,qr);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
P[0]=1;
for (int i=1;i<=n;++i) P[i]=P[i-1]*PP%MO;
//build2(1,1,n);
bool flag=0;
for (int i=1;i<=n;++i)
{
int len=min(a[i]-1,n-a[i]);
//printf("%d %d\n",i,len);
if (len>=1)
{
res1=0; query1(1,1,n,a[i]-len,a[i]-1);
res2=0; query2(1,1,n,a[i]+1,a[i]+len);
//printf("%d %d\n",res1,res2);
if (res1!=res2) { flag=1; break; }
}
update1(1,1,n,a[i]); update2(1,1,n,a[i]);
}
if (flag) printf("YES\n");
else printf("NO\n");
return 0;
}