我们容易发现一个事实,假设 能够成为一个答案,那么
一定也是一个答案,也就是说,当我们固定
时,一定存在一个分界点
,使得
到
都是答案,而
到
都不是答案。所以对每个
,考虑二分这个分界点
,每次只需要判断
是不是答案,然后缩小范围即可。
而判断 是不是答案是容易的,我们可以暴力处理出来
和
,然后判断
是不是
的子序列即可,显然这是容易做到的。
时间复杂度 ,通过绰绰有余了。代码:
#include<bits/stdc++.h>
#define ll long long
#define vec vector
#define pb push_back
using namespace std;
ll n,a[2005],b[2005],c[2005],ans=0;
bool ck(ll l,ll r){
ll tot=0,cnt=0,pos=1;
for(ll i=1;i<l;i++) b[++tot]=a[i];
for(ll i=r+1;i<=n;i++) b[++tot]=a[i];
for(ll i=l;i<=r;i++) c[++cnt]=a[i];
for(ll i=1;i<=cnt;i++){
while(pos<=tot&&b[pos]!=c[i]) pos++;
if(pos>tot) return false;
pos++;
}
return true;
}
int main(){
cin>>n;
for(ll i=1;i<=n;i++) cin>>a[i];
for(ll i=2;i<n;i++){
ll l=i,r=n-1,res=0;
while(l<=r){
ll md=(l+r)>>1;
if(ck(i,md)){
l=md+1;
res=md;
}else{
r=md-1;
}
}
ans+=(!res?0:res-i+1);
}
cout<<ans<<endl;
}

京公网安备 11010502036488号