社区讨论

对于一道站外题(难度大概csps T2)

学术版参与者 6已保存回复 5

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
5 条
当前快照
1 份
快照标识符
@miv63rvt
此快照首次捕获于
2025/12/07 11:33
2 个月前
此快照最后确认于
2025/12/09 22:00
2 个月前
查看原帖
题目描述 今天 syy 和同学们一起出去春游,正准备回学校时,班主任临时告诉 syy 希望他可以给全班同学拍一个合照
班级里总共有 n n 个同学从左往右排成一队,每个同学有自己的身高,第 i i 个同学的身高为 a i a i ​
一般合照要好看的话都是在中间形成一个峰:类似于 [ 1 , 2 , 3 , 2 , 1 ] [1,2,3,2,1] 这种形式,但是来接的大巴车马上就要到了,看着随意排成一队的同学们,再重新排队肯定是来不及了!
于是 syy 决定不让同学们再移动了,他可以将现在的队伍分成前中后三段,各拍一张照片。
其中第一张照片和最后一张照片中身高最高的同学身高,刚好等于中间这张照片中身高最矮的同学身高。
若能够拍出这样的照片, syy 就可以用软件合成出一张完美的合照。
当然,在拍照时不能漏下班里任何一个同学。
现在时间紧急,syy 只能向你求助,请你帮他计算一下他能否拍出这样的照片,若能,则告诉他从左往右三张照片中分别有多少人。
输入格式 输入第一行为一个正整数 T
T 表示有多少组测试数据
对于每组测试数据满足:
输入第一行包含一个正整数 n
n 表示有多少同学
输入第二行包含 n 个正整数
a 1 , a 2 . . . a n a 1 ​ ,a 2 ​ ...a n ​
分别表示每个同学的身高 输出格式 对于每组测试数据:
第一行输出 YES 或者 NO 表示能否拍出这样的照片
若第一行输出为 YES,则在第二行输出三个正整数分别表示从左往右每张照片中的人数,若存在多种方案,输出字典序最小的那一组。
输出的 YES 和 NO 不包含引号
t<=1000
3<=n<300000
ai<=1000000000```cpp #include<bits/stdc++.h> using namespace std; int t,n,a[500001],pre[500001],suf[500001],min2; //(i)类情况返回1 //(ii)类情况返回2 //(iii)返回3 //(iiii)返回4
//思路:枚举第一个分割点,二分第二个分割点 //(i)如果1的最大值小于2的最小值,让2的最小值更小,l=mid+1 //(ii)如果1的最大值大于2的最小值,让2的最小值更大,r=mid-1 //(iii)如果1的最大值大于3的最大值,让3的最大值更大,r=mid-1 //(iiii)如果1的最大值小于3的最大值,让3 的最大值小,l=mid+1 int check(int div1,int div2){ int maxn1=pre[div1],minn2=INT_MAX,maxn3=suf[div2]; for(int i=div1+1;i<div2;i++){ minn2=min(minn2,a[i]); } min2=minn2; if(maxn1<minn2){ return 1; } if(maxn1>minn2){ return 2; } if(maxn1>maxn3){ return 3; } if(maxn1<maxn3){ return 4; }
} int main(){ cin>>t; for(int p=1;p<=t;p++){ cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; pre[i]=pre[i-1]; pre[i]=max(pre[i],a[i]); } for(int l=n;l>=1;l--){ suf[l]=suf[l+1]; suf[l]=max(suf[l],a[l]); } } //思路:枚举第一个分割点,二分第二个分割点 //(i)如果1的最大值小于2的最小值,让2的最小值更小,l=mid+1 //(ii)如果1的最大值大于2的最小值,让2的最小值更大,r=mid-1 //(iii)如果1的最大值大于3的最大值,让3的最大值更大,r=mid-1 //(iiii)如果1的最大值小于3的最大值,让3 的最大值小,l=mid+1 for(int i=1;i<=n;i++){ int l=i+1,r=n,mid; while(l<=r){ mid=(l+r)/2; if(check(i,mid)==1){ l=mid+1; } if(check(i,mid)==2){ r=mid-1; } if(check(i,mid)==3){ r=mid-1; } if(check(i,mid)==4){ l=mid+1; } } if(pre[i]==suf[mid]&&pre[i]==min2){ cout<<i<<mid-i<<n-mid; return 0; } } return 0; }
CPP


求条

回复

5 条回复,欢迎继续交流。

正在加载回复...