「赛后总结」20220212 模拟赛题解
比赛传送门
T1吃
题意
有 \(n\) 个桌子,每个桌子上有两样吃的。想要选出连续的一段桌子,然后从每个桌子食物种类一样的食物吃下去。求他最多能吃多少个食物以及食物的最小标号。
思路
设 \(f_{i,j}\) 表示第 \(i\) 个桌子有多少个连续的种类为 \(j\) 的食物。
\(f_{i,j}=f_{i-1,j}+1\),暴力转移即可。
代码
#include <bits/stdc++.h>
#define _for(i,a,b) for(ll i=a;i<=b;++i)
#define for_(i,a,b) for(ll i=a;i>=b;--i)
#define ll long long
using namespace std;
const int N=1e5+10,inf=0x3f3f3f3f;
int n,a[N],b[N],zl,f[N][10],ans,w;
int main(){
scanf("%d",&n);
_for(i,1,n){
scanf("%d%d",&a[i],&b[i]);
if(a[i]>b[i])swap(a[i],b[i]);
f[i][a[i]]=f[i-1][a[i]]+1;
f[i][b[i]]=f[i-1][b[i]]+1;
int mx,z;
if(f[i][a[i]]<=f[i][b[i]])mx=f[i][b[i]],z=b[i];
else mx=f[i][a[i]],z=a[i];
if(mx>ans||(mx==ans&&z<w))ans=mx,w=z;
}printf("%d %d\n",ans,w);
return 0;
}
T2糖
题意
有 \(m\) 颗糖,把它分给 \(n\) 个人。
第 \(i\) 个人对于分到糖果的预期值是 \(a_i\)。
设第 \(i\) 个人得到了 \(b_i\) 颗糖果(\(b_i\le a_i\)),最小化: $$\sum^{i\le n}_{i=1}(a_i-b_i)^2$$
思路
首先我们要让 \(a_i-b_i\) 的值尽量平均(很好看出这个策略是正确的,例如 \(1^2+3^2>2^2+2^2\))。
令: $$c=\sum^{i\le n}_{i=1}a_i-m$$
我们可以让每一个 \(a_i-b_i\) 都等于 \(\lfloor\frac{c}{n}\rfloor\)
如果 \(a_i\le \lfloor\frac{c}{n}\rfloor\) ,则把 \({a_i}^2\) 累计入答案,把没用上的均摊给其它数而不是这个数
代码
#include <bits/stdc++.h>
#define _for(i,a,b) for(ll i=a;i<=b;++i)
#define for_(i,a,b) for(ll i=a;i>=b;--i)
#define ll long long
using namespace std;
const int N=1e5+10,inf=0x3f3f3f3f;
ll n,m,a[N],sum,ans;
int main(){
scanf("%lld%lld",&m,&n);
_for(i,1,n){
scanf("%lld",&a[i]);
sum+=a[i];
}
sort(a+1,a+n+1);
if(m>=sum)printf("0\n");
else{
ll c=sum-m,k=n;
_for(i,1,n){
ll pj=c/k;
if(a[i]<=pj)c-=a[i],--k,ans+=a[i]*a[i];
else break;
}
ans+=(k-c%k)*(c/k)*(c/k);
ans+=(c%k)*(c/k+1)*(c/k+1);
printf("%lld",ans);
}
return 0;
}
T3数
题意
给出一个长度为 \(n\) 的序列,求:
思路
首先我们把式子拆成:
考虑如何求这两坨。
对于每个 \(a_i(1\le i\le n)\),我们把它当成某些区间的最大值/最小值,看他在哪一个长度尽量大的区间是最大值/最小值,那么这个区间内 \(i\) 左边的点就是可行的左端点,右边的点就是可行的右端点。可行的左端点的数量 \(*\) 可行的右端点的数量,就是这些区间的个数。可行区间的个数乘 \(a_i\) 就是它产生的贡献了。
那我们又如何去求这个最大区间呢?
代码
#include <bits/stdc++.h>
#define _for(i,a,b) for(ll i=a;i<=b;++i)
#define for_(i,a,b) for(ll i=a;i>=b;--i)
#define ll long long
using namespace std;
const int N=3e5+10,inf=0x3f3f3f3f;
ll n,a[N],mn[N][2],mx[N][2],ans;
ll s[N],ts,t[N],tt;
map<ll,ll>mp;
int main(){
scanf("%lld",&n);
_for(i,1,n)scanf("%lld",&a[i]);
a[0]=a[n+1]=inf;
_for(i,1,n+1){
while(ts>0&&a[s[ts]]<=a[i]){
mx[s[ts]][0]=i-s[ts];
ts--;
}s[++ts]=i;
}ts=0;
for_(i,n,0){
while(ts>0&&a[s[ts]]<a[i]){
mx[s[ts]][1]=s[ts]-i;
ts--;
}s[++ts]=i;
}a[0]=a[n+1]=0;
_for(i,1,n+1){
while(tt>0&&a[t[tt]]>=a[i]){
mn[t[tt]][0]=i-t[tt];
tt--;
}t[++tt]=i;
}tt=0;
for_(i,n,0){
while(tt>0&&a[t[tt]]>a[i]){
mn[t[tt]][1]=t[tt]-i;
tt--;
}t[++tt]=i;
}
_for(i,1,n)ans+=a[i]*(mx[i][0]*mx[i][1]-mn[i][0]*mn[i][1]);
printf("%lld",ans);
return 0;
}
T4膜
题意
咕咕咕
思路
咕咕咕
代码
#include <bits/stdc++.h>
#define _for(i,a,b) for(ll i=a;i<=b;++i)
#define for_(i,a,b) for(ll i=a;i>=b;--i)
#define ll long long
using namespace std;
const int N=1e5+10,inf=0x3f3f3f3f;
ll t,n,m;
inline ll read(){
ll x=0,w=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w*x;
}bool check(ll md){
__int128 c=md,sum=md;
_for(i,0,m-2){
c=c*(md-(i+1))/(i+2);
if(c>=n)return 1;
sum+=c;
if(sum>=n)return 1;
}return sum>=n;
}
int main(){
t=read();
while(t--){
n=read(),m=read();
ll l=1,r=n;
while(l<r){
ll mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}printf("%lld\n",r);
}
return 0;
}

浙公网安备 33010602011771号