这周忙死,一直没机会吧补一下题,周二晚上打的div3,过了A~E,F就看了下题目就没时间了,无聊的时候想应该会用到ST表,然后想要维护指针,后来写的时候发现维护不了,然后就歇菜了。。。
F. Array Partition
大佬题解
枚举一个断点,然后二分一个断点。
三个区间分别为[1,i−1],[i,mid],[mid+1,n][1,i-1],[i,mid],[mid+1,n][1,i−1],[i,mid],[mid+1,n]
对于枚举的端点iii显然max(1,i−1)max(1,i-1)max(1,i−1)以固定,考虑如何确定midmidmid
- 若min(i,mid)>max(1,i−1)min(i,mid)>max(1,i-1)min(i,mid)>max(1,i−1) 需要扩大中间的区间使min(i,mid)min(i,mid)min(i,mid)变小
- 若min(i,mid)<max(1,i−1)min(i,mid)<max(1,i-1)min(i,mid)<max(1,i−1) 需要缩小中间的区间使min(i,mid)min(i,mid)min(i,mid)变大
- 若min(i,mid)=max(1,i−1)min(i,mid)=max(1,i-1)min(i,mid)=max(1,i−1)
1.若min(i,mid)>max(mid+1,n)min(i,mid)>max(mid+1,n)min(i,mid)>max(mid+1,n) 需要缩小中间的区间
2.若min(i,mid)<max(mid+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;
}
奇怪的二分~~不会啊!
要加油哦~