2025年8月月赛 T2 T3
一. 七天假日 T2
原思路:直接计算左右括号的数量,然后直接输出他们的差
改进思路: 用d值记录截止到当前位置,还需要多少个右括号可以满足非法要求
cur:截止到当前位置,已经有多少个右括号
sum是右括号位置的前缀和;
假设当前位置为i,需要从i开始有d+1个右括号,那么从0到i+d的字符串就是一个非法的字符串: sum[cur+d+1]-sum[cur]是后面d+1右括号的位置和,我要把这d+1个右括号移动到 i-d+i ,i-d+i的位置和使用等差数列求和(i+i+d)*(d+1)/2 差值最小值就是答案
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int sum[N],t;
signed main(){cin>>t;while(t--){string s;cin>>s;int n=s.size()/2;for(int i=0,j=0;i<n*2;i++){if(s[i]==')')sum[++j]=i;}for(int i=1;i<=n;i++)sum[i]+=sum[i-1];int d=0,cur=0,ans=9e18;for(int i=0;i<n*2;i++){if(cur+d+1<=n) ans=min(ans,sum[cur+d+1]-sum[cur]-(2*i+d)*(d+1)/2);if(s[i]=='(') d++;else d--,cur++;}cout<<ans<<endl;}return 0;
}
/*
3
()
(())
(()()())(((())))(()())
*/
二.辛酸风味 T3
需要保证平均数也是中位数
如果平均数比中位数大 那么我们需要保证中位数到这个二分的值全是mid才能保证
中位数=平均数,差值为res 左边界为max((所有数的和+n-1)/n,a[中位值]),右边界为1e9
随后进行二分操作 如果n*mid-res-sum 则mid为答案
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
int t,n,a[N],s[N],sum;
signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0); cin>>t;while(t--){cin>>n;sum=0;for(int i=1;i<=n;i++){cin>>a[i];sum+=a[i];}sort(a+1,a+n+1);for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i];int pos=(n+1)/2,res=0;int l=max((sum+n-1)/n,a[pos]),r=1e9;while(l<r){int mid=l+r>>1;int x=lower_bound(a+1,a+n+1,mid)-a;if(x>=pos) res=(x-pos)*mid-(s[x-1]-s[pos-1]);else res=0;if(n*mid-sum-res>=0) r=mid;else l=mid+1;}cout<<n*l-sum<<endl;}return 0;
}