题解:CF1647F Madoka and Laziness
题目传送门
题意
给定一个长度为
思路
注意到,序列中每个数都不相同。所以,一定有一个子序列一直包含着序列中的最大值。所以方案数一定不会超过
那么根据
在
代码如下:
m1=m2=0;
for(int i=1;i<=pos;i++){
if(a[i]>m1)m1=a[i];
else if(a[i]>m2)m2=a[i];
else return;
}
如果这个数可以给序列
同理,在
代码如下:
for(int i=n;i>pos;i--){
if(a[i]>m2)m2=a[i];
else if(a[i]>m1)m1=a[i];
else break;
dp1[i]=m1,dp2[i]=m2;
}
最后一种情况就是
代码如下:
for(int i=pos+1;i<=n;i++){
if(a[i]>m2&&(a[i]>m1||a[i]<a[i+1]))m2=a[i];
else if(a[i]<m1)m1=a[i];
else break;
ans+=(m1>dp1[i]&&m2<=dp2[i]);
}
最后不要忘记 把整个序列翻转,再做一遍。
完整代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1010101;
const ll inf=1e18;
ll n,ans,a[N],dp1[N],dp2[N];
void solve(){
ll pos=0,m1=0,m2=0;
for(int i=1;i<=n;i++)dp1[i]=1e9,dp2[i]=0;
for(int i=1;i<=n;i++)if(a[i]>a[pos])pos=i;
for(int i=n;i>pos;i--){
if(a[i]>m2)m2=a[i];
else if(a[i]>m1)m1=a[i];
else break;
dp1[i]=m1,dp2[i]=m2;
}
m1=m2=0;
for(int i=1;i<=pos;i++){
if(a[i]>m1)m1=a[i];
else if(a[i]>m2)m2=a[i];
else return;
}
for(int i=pos+1;i<=n;i++){
if(a[i]>m2&&(a[i]>m1||a[i]<a[i+1]))m2=a[i];
else if(a[i]<m1)m1=a[i];
else break;
ans+=(m1>dp1[i]&&m2<=dp2[i]);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
solve();
reverse(a+1,a+n+1);
solve();
cout<<ans<<'\n';
return 0;
}