Atcoder Beginner Contest 330 题解
AtCoder Beginner Contest 330 题解
A - Counting Passes 签到
void Showball(){
int n,l;
cin>>n>>l;
int cnt=0;
for(int i=0;i<n;i++){
int x;
cin>>x;
cnt+=(x>=l);
}
cout<<cnt<<endl;
}
B - Minimize Abs 1 思维
void Showball(){
int n,l,r;
cin>>n>>l>>r;
vector<int> a(n);
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++){
if(a[i]>r) cout<<r<<" ";
else if(a[i]<l) cout<<l<<" ";
else cout<<a[i]<<" ";
}
}
C - Minimize Abs 2 二分
枚举\(x\),二分\(y\)。更新答案即可。
LL sq[N];
void Showball(){
for(int i=1;i<N;i++) sq[i]=1LL*i*i;
LL d;
cin>>d;
LL ans=1e18;
for(LL i=1;i*i<=d;i++){
LL cur=d-i*i;
int j=lower_bound(sq,sq+N,cur)-sq;
if(sq[j]==cur) return cout<<0<<endl,void();
ans=min(ans,abs(cur-sq[j]));
ans=min(ans,abs(cur-sq[j-1]));
}
cout<<ans<<endl;
}
D - Counting Ls 计数
定义:
\(col[i]\)表示第\(i\)行 '\(o\)' 数量。
\(row[j]\)表示第\(j\)列 '\(o\)' 数量。
那么对于任意一个\((i,j)\)满足\(a[i][j]==\)'\(o\)',对答案的贡献即为\((col[i]-1)\times(row[j]-1)\)。
因为不存在和\((i,j)\)同行且同列的情况。所以计算结果不重不漏。
char a[N][N];
int col[N],row[N];
void Showball(){
int n;
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>a[i][j];
if(a[i][j]=='o'){
col[i]++;
row[j]++;
}
}
}
LL ans=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(a[i][j]=='o'){
ans+=(col[i]-1)*(row[j]-1);
}
}
}
cout<<ans<<endl;
}
E - Mex and Update 思维 诈骗
单调修改,求整体\(mex\)。
根据mex的性质,那么范围只可能\([0,n]\)。
用数组去统计每个数出现的次数,先将次数为0的全部放进\(set\),那么\(set\)中最小值就是\(mex\)。
对于单点修改,我们直接更新次数,并且维护一下\(set\)即可。
void Showball(){
int n,q;
cin>>n>>q;
vector<int> a(n),cnt(n+1);
set<int> s;
for(int i=0;i<n;i++){
cin>>a[i];
if(a[i]<=n) cnt[a[i]]++;
}
for(int i=0;i<=n;i++) if(!cnt[i]) s.insert(i);
while(q--){
int x,v;
cin>>x>>v;
x--;
if(a[x]<=n){
if(!--cnt[a[x]]) s.insert(a[x]);
}
if(v<=n){
if(++cnt[v]==1) s.erase(v);
}
a[x]=v;
cout<<*s.begin()<<endl;
}
}
F - Minimize Bounding Square 二分答案
要求边长的最小值,容易想到二分答案。
考虑\(check\)函数如何去写,那么就需要去求出所有点到变成为\(h\)正方形的最短距离之和。
我们发现横纵坐标相互之间没有影响,所以可以分开进行计算。
我们只知道正方形的边长,却不知道正方形的位置。所以正方形可以进行平移至理想情况。
所以我们发现如果两个端点在正方形的外面,那么移动次数就为\(y_1-y_2-h\)。而两个在里面的情况,移动次数就为\(0\)。所以我们可以对横纵坐标排序。那么每次的移动次数就是\((x[n-i-1]-x[i]-h)\),显然如果小于\(0\),说明都在里面,记为\(0\)即可。
void Showball(){
int n;
LL k;
cin>>n>>k;
vector<int> x(n),y(n);
for(int i=0;i<n;i++) cin>>x[i]>>y[i];
sort(all(x));
sort(all(y));
auto check=[&](int h){
LL cnt=0;
for(int i=0;i<=n/2;i++){
cnt+=max(0,x[n-i-1]-x[i]-h);
cnt+=max(0,y[n-i-1]-y[i]-h);
}
return cnt<=k;
};
int l=0,r=1e9+1;
while(l<r){
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l<<endl;
}