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)×(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正方形的最短距离之和。

我们发现横纵坐标相互之间没有影响,所以可以分开进行计算。

我们只知道正方形的边长,却不知道正方形的位置。所以正方形可以进行平移至理想情况。

所以我们发现如果两个端点在正方形的外面,那么移动次数就为y1y2h。而两个在里面的情况,移动次数就为0。所以我们可以对横纵坐标排序。那么每次的移动次数就是(x[ni1]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;
}
posted @   Showball  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示