题目
给你一个大小为n的数组A,以及一个X和Y。
要求求出满足最大值为X且最小值为Y的区间数量。
数据范围
题解思路
很久没写双指针题了,有点不太行,所以一直没自己补出来,一开始看的dls的状压dp
dp[i][0/1][0/1] 定义为以i为右端点的连续区间中 有或者没有最小值Y
有或者没有最大值X的数量。
再通过此时的a[i]值来更新到这个点的数量。
每次取dp[i][1][1]即可。
梦中把这题用双指针补了。
结果思路真是对的,官方题解也讲了双指针,可惜我看不懂英文。
所以才只能自己推。
我们只需维护双指针的区间中具有几个XY以及从i点能取的区间的 最小右端点以及左端点 且保证区间中的数都是在范围里面的。
当i为X或者Y的时候,我们需要对应的更新区间的XY数量,以及能取的最小右端点,我们得预处理出每个XY对应的下个XY,当这个点被删除了我们只能取下个点对之前的点取max。
AC代码
双指针写法
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define int long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1000100;
int a[N] ;
void solve()
{
int n , x , y ;
cin >> n >> x >> y ;
long long ans = 0 ;
for (int i = 1 ; i <= n ; i++ )
cin >> a[i] ;
map <int , int > mp ;
int lastx = 0 ;
for (int i = 1 ; i <= n ; i++ )
{
if (a[i] == x )
{
if (!lastx)
lastx = i ;
else
{
mp[lastx] = i ;
lastx = i ;
}
}
}
lastx = 0 ;
for (int i = 1 ; i <= n ; i++ )
{
if (a[i] == y )
{
if (!lastx)
lastx = i ;
else
{
mp[lastx] = i ;
lastx = i ;
}
}
}
int mac = 0 , mic = 0 , spj = 0 ;
for (int i = 1 , j = 1 ; i <= n ; i++ )
{
if ( a[i] > x || a[i] < y )
{
mac = 0 , mic = 0 , spj = 0 ;
continue;
}
if ( i > j )
j = i ;
while ( j <= n )
{
if (a[j] > x || a[j] < y )
break;
if (a[j] == x )
mac++;
if (a[j] == y )
mic++;
if (spj == 0 && mac && mic )
spj = j ;
j++;
}
if (spj != 0 && mac && mic)
{
ans += j - spj ;
//cout << i << " " << spj << " " << j << "\n" ;
}
if (a[i] == x )
mac--, spj = max(mp[i],spj) ;
if (a[i] == y )
mic--, spj = max(mp[i],spj) ;
if ( spj >= j )
spj = 0 ;
//cout << mac << " " << mic << " " << spj << "\n" ;
if (mac == 0 || mic == 0 )
spj = 0 ;
}
cout << ans << "\n" ;
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
solve() ;
return 0 ;
}
DP写法
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200100;
int a[N] ;
long long dp[N][3][3] ;
void solve()
{
int n ;
int x , y ;
cin >> n >> x >> y ;
for (int i = 1 ; i <= n ; i++ )
cin >> a[i] ;
long long ans = 0 ;
for (int i = 1 ; i <= n ; i++ )
{
if (a[i] < y || a[i] > x )
continue;
int fs = a[i] == x , ft = a[i]==y ;
dp[i][fs][ft] += 1 ;
for (int j = 0 ; j < 2 ; j++ )
for (int k = 0 ; k < 2 ; k++ )
dp[i][j|fs][k|ft] += dp[i-1][j][k] ;
ans += dp[i][1][1] ;
}
cout << ans << "\n" ;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
solve() ;
return 0 ;
}