Atcoder Beginner Contest 379 (A-F)

Atcoder Beginner Contest 379 (A-F)

题目链接

A - Cyclic

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    char a,b,c;
    cin>>a>>b>>c;
    cout<<b<<c<<a<<" "<<c<<a<<b<<"\n"; 
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

    while(t--){
      Showball();
    }

    return 0;
}

B - Strawberries

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    int n,k;
    cin>>n>>k;
    string s;
    cin>>s;
    int ans=0;
    for(int i=0,j=0;i<n;){
        while(j<n&&s[j]==s[i]) j++;
        if(s[i]=='O') ans+=(j-i)/k;
        i=j; 
    } 
    cout<<ans<<"\n";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

    while(t--){
      Showball();
    }

    return 0;
}

C - Sowing Stones

对比其余 \(C\) 题,算是有点难度的。首先如果棋子之和不等于 \(n\) ,或者最小的 \(x_i\) 不为 \(1\) ,那么无解。

因为每个棋子只能往后移动,因此我们直接贪心往后放即可。相邻的 \(x_i\) 之间的都需要移动,发现贡献是一个等差数列。

直接求即可。如果数量不够,说明无解。多的棋子直接给下一个 \(x_i\) ,注意这部分也要算贡献。最后判断一下棋子有没有剩余即可。

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    int n,m;
    cin>>n>>m;
    vector<pair<int,int>> a(m+1);
    for(int i=0;i<m;i++) cin>>a[i].first;
    i64 sum=0;    
    for(int i=0;i<m;i++) {
        int x;
        cin>>x;
        sum+=x;
        a[i].second=x;
    }
    a[m].first=n+1;
    sort(a.begin(),a.end());
    if(sum!=n||a[0].first!=1) return cout<<"-1\n",void();

    i64 ans=0;
    for(int i=0;i<m;i++){
        a[i].second--;
        int d=a[i+1].first-a[i].first-1;
        if(a[i].second<d) return cout<<"-1\n",void();
        ans+=1LL*d*(d+1)/2;
        if(a[i].second>d){
            a[i+1].second+=(a[i].second-d);
            ans+=1LL*(a[i].second-d)*(a[i+1].first-a[i].first);
        }
    }
    if(a[m].second) ans=-1;
    cout<<ans<<"\n";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

    while(t--){
      Showball();
    }

    return 0;
}

D - Home Garden 思维

因为只有全局加操作,因此我们可以使用类似懒标记的思想,将所有的加操作加到标记上,那么插入一个新花盆的时候,我们可以赋初值为 \(-sum\) 。然后维护好单调性,有多少个大于 \(h\) 我们直接二分即可。

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    int q;
    cin>>q;
    int hh=q,tt=q;
    vector<i64> a(q);

    i64 sum=0;
    while(q--){
        int op;
        cin>>op;
        if(op==1){
            a[--hh]=-sum;
        }else if(op==2){
            int t;
            cin>>t;
            sum+=t;
        }else{
            int h;
            cin>>h;
            int p=lower_bound(a.begin()+hh,a.begin()+tt,h-sum)-(a.begin()+hh);
            cout<<tt-hh-p<<"\n";
            tt=hh+p;
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

    while(t--){
      Showball();
    }

    return 0;
}

E - Sum of All Substrings

经典的拆分算贡献的题目,我们发现每一位数字的贡献为 \(i\times a_i \times(10^0+10^1+...+10^{n-i})\)

等差数列求和即可。但是本题数据范围很大,要用高精度,复杂难写。我们可以用数组存取每一位的系数,

那么每次操作,就相当于区间加上一个系数,用差分解决即可。最后模拟处理一下进位即可。

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    int n;
    cin>>n;
    string s;
    cin>>s;
    s="?"+s;
    vector<i64> a(500010);
    for(int i=1;i<=n;i++){
        int x=n-i+1,y=i*(s[i]-'0');
        a[1]+=y;a[x+1]-=y;
    }

    for(int i=1;i<=n;i++) a[i]+=a[i-1];

    i64 k=0;
    for(int i=1;i<=n;i++){
        a[i]+=k;
        k=a[i]/10;
        a[i]%=10;
    }
    int cnt=n;
    while(k){
        a[++cnt]=k%10;
        k/=10;
    }

    for(int i=cnt;i;i--) cout<<a[i];
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

    while(t--){
      Showball();
    }

    return 0;
}

F - Buildings 2

首先我们可以知道:\(l\) 能够看到的建筑物 \(r\) 一定能够看到, \(r\) 能够看到的建筑物 \(l\) 不一定能够看到。

因此想要找 \(l,r\) 都能够看到的建筑物,只需要去找 \(l\) 能够看到的建筑物中位置在 \(r\) 右边的即可。

考虑离线,将询问按照左端点进行分类。每个位置能够看到的建筑物,我们可以倒着维护一个单调队列。

然后在这个单调队列上进行二分即可。

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    int n,q;
    cin>>n>>q;
    vector<int> h(n+1);
    vector<array<int,2>> Q[n+1];
    for(int i=1;i<=n;i++) cin>>h[i];
    for(int i=1;i<=q;i++){
        int l,r;
        cin>>l>>r;
        Q[l].push_back({r,i});
    }  

    vector<int> st(n+1),ans(q+1);
    int cnt=0;
    for(int i=n;i;i--){
        for(auto [j,id]:Q[i]){
            int l=1,r=cnt;
            while(l<r){
                int mid=l+r+1>>1;
                if(st[mid]>j) l=mid;
                else r=mid-1;
            }
            if(st[l]<=j) ans[id]=0;
            else ans[id]=l;
        }
        while(cnt&&h[st[cnt]]<h[i]) cnt--;
        st[++cnt]=i;
    }

    for(int i=1;i<=q;i++) cout<<ans[i]<<"\n";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

    while(t--){
      Showball();
    }

    return 0;
}
posted @ 2024-11-14 19:44  Showball  阅读(3)  评论(0编辑  收藏  举报