这周忙死,一直没机会吧补一下题,周二晚上打的div3,过了A~E,F就看了下题目就没时间了,无聊的时候想应该会用到ST表,然后想要维护指针,后来写的时候发现维护不了,然后就歇菜了。。。
F. Array Partition
大佬题解
枚举一个断点,然后二分一个断点。
三个区间分别为
[
1
,
i
−
1
]
,
[
i
,
m
i
d
]
,
[
m
i
d
+
1
,
n
]
[1,i-1],[i,mid],[mid+1,n]
[1,i−1],[i,mid],[mid+1,n]
对于枚举的端点 i i i显然 m a x ( 1 , i − 1 ) max(1,i-1) max(1,i−1)以固定,考虑如何确定 m i d mid mid
- 若 m i n ( i , m i d ) > m a x ( 1 , i − 1 ) min(i,mid)>max(1,i-1) min(i,mid)>max(1,i−1) 需要扩大中间的区间使 m i n ( i , m i d ) min(i,mid) min(i,mid)变小
- 若 m i n ( i , m i d ) < m a x ( 1 , i − 1 ) min(i,mid)<max(1,i-1) min(i,mid)<max(1,i−1) 需要缩小中间的区间使 m i n ( i , m i d ) min(i,mid) min(i,mid)变大
- 若
m
i
n
(
i
,
m
i
d
)
=
m
a
x
(
1
,
i
−
1
)
min(i,mid)=max(1,i-1)
min(i,mid)=max(1,i−1)
1.若 m i n ( i , m i d ) > m a x ( m i d + 1 , n ) min(i,mid)>max(mid+1,n) min(i,mid)>max(mid+1,n) 需要缩小中间的区间
2.若 m i n ( i , m i d ) < m a x ( m i d + 1 , n ) min(i,mid)<max(mid+1,n) min(i,mid)<max(mid+1,n) 需要扩大中间的区间
3.找到答案直接输出
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=998244353;
const int N=200010;
int n,a[N];
int STmn[N][19],STmx[N][19],lg[N];
void pre()
{
lg[1]=0;
for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
for(int i=1;i<=n;i++) STmx[i][0]=STmn[i][0]=a[i];
for(int j=1;j<=lg[n];j++)
for(int i=1;i+(1<<j)-1<=n;i++)
{
STmn[i][j]=min(STmn[i][j-1],STmn[i+(1<<j-1)][j-1]);
STmx[i][j]=max(STmx[i][j-1],STmx[i+(1<<j-1)][j-1]);
}
}
int qmin(int l,int r)
{
int len=lg[r-l+1];
return min(STmn[l][len],STmn[r-(1<<len)+1][len]);
}
int qmax(int l,int r)
{
int len=lg[r-l+1];
return max(STmx[l][len],STmx[r-(1<<len)+1][len]);
}
int main()
{
//IO;
int T=1;
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
pre();
bool ok=0;
for(int i=2;i<n;i++)
{
if(ok) break;
int l=i,r=n-1;
while(l<=r)
{
int mid=l+r>>1;
if(qmin(i,mid)>qmax(1,i-1)) l=mid+1;
else if(qmin(i,mid)<qmax(1,i-1)) r=mid-1;
else
{
if(qmin(i,mid)>qmax(mid+1,n)) r=mid-1;
else if(qmin(i,mid)<qmax(mid+1,n)) l=mid+1;
else
{
ok=1;
cout<<"YES\n";
cout<<i-1<<' '<<mid-i+1<<' '<<n-mid<<'\n';
break;
}
}
}
}
if(!ok) cout<<"NO\n";
}
return 0;
}
奇怪的二分~~不会啊!
要加油哦~