首页 > 其他分享 >AtCoder Beginner Contest 373 (A-F)

AtCoder Beginner Contest 373 (A-F)

时间:2024-10-11 15:13:05浏览次数:1  
标签:Showball AtCoder return Beginner int long -- using 373

AtCoder Beginner Contest 373 (A-F)

比赛链接

A - September

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    int ans=0;
    for(int i=1;i<=12;i++){
        string s;
        cin>>s;
        ans+=((int)s.size()==i);
    } 
    cout<<ans<<"\n";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

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

    return 0;
}

B - 1D Keyboard

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    string s;
    cin>>s;
    vector<int> p(26);
    for(int i=0;i<26;i++){
        p[s[i]-'A']=i;
    }
    int ans=0;
    for(int i=1;i<26;i++){
        ans+=abs(p[i]-p[i-1]);
    }
    cout<<ans<<"\n";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

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

    return 0;
}

C - Max Ai+Bj

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    int n;
    cin>>n;
    vector<int> a(n),b(n);
    for(int i=0;i<n;i++) cin>>a[i]; 
    for(int i=0;i<n;i++) cin>>b[i];
    cout<<*max_element(a.begin(),a.end())+*max_element(b.begin(),b.end()); 
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

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

    return 0;
}

D - Hidden Weights 图论+构造

思路

直接建一条等价的反向边,然后DFS构造即可。

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    int n,m;
    cin>>n>>m;
    vector<vector<array<i64,2>>> e(n);
    while(m--){
        int u,v,w;
        cin>>u>>v>>w;
        u--;
        v--;
        e[u].push_back({v,w});
        e[v].push_back({u,-w});
    }   

    vector<i64> vis(n),ans(n);
    function<void(int)> dfs=[&](int u){
        if(vis[u]) return;
        vis[u]=1;
        for(auto [v,w]:e[u]){
            ans[v]=ans[u]+w;
            dfs(v);
        }
    };

    for(int i=0;i<n;i++) dfs(i);
    for(auto x:ans) cout<<x<<" ";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

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

    return 0;
}

E - How to Win the Election 二分答案

思路

考虑二分答案,令 \(w\) 表示当前候选人的选票数量,\(check\) 函数判断大于等于 \(w+1\) 的数量是否大于等于 \(m\) 即可。如果已经有 \(m\) 个选票大于 \(w+1\) 那么直接 \(return false\)。否则,我们判断将剩下的补够 \(m\) 个选票数量是否足够即可。排序后,前缀和可以快速求出所需选票数量。注意,如果当前候选人也属于最大的 \(m\) 个选票时,需要筛除掉。特判一下即可。具体实现看代码。

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
     i64 n,m,k;
     cin>>n>>m>>k;
     vector<i64> a(n+1),b(n+1),p(n+1),s(n+1);
     for(int i=1;i<=n;i++){
        cin>>a[i];
        p[i]=i;
     }

     if(m==n){
        for(int i=1;i<=n;i++){
            cout<<0<<" ";
        }
        return;
     }
     sort(p.begin()+1,p.end(),[&](int x,int y){
        return a[x]<a[y];
     });

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

     auto check=[&](int i,i64 mid)->bool{
        i64 w=a[p[i]]+mid+1;
        if(w<=b[n-m+1]) return false;
        int l=n-m+1,r=n;
        while(l<r){
            int mid=l+r+1>>1;
            if(b[mid]<w) l=mid;
            else r=mid-1;
        }
        i64 v=k-s[n]-mid;
        if(i>n-m){
            v-=w*(l-(n-m))-(s[l]-s[n-m-1]-b[i]);
        }else{
            v-=w*(l-(n-m))-(s[l]-s[n-m]);
        }
        return v<0;
     };

     vector<i64> ans(n+1);
     for(int i=1;i<=n;i++){
        i64 l=0,r=k-s[n];
        while(l<r){
            i64 mid=l+r>>1;
            if(check(i,mid)) r=mid;
            else l=mid+1;
        }
        ans[p[i]]=(check(i,l)?l:-1);
     }
     for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

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

    return 0;
}

F - Knapsack with Diminishing Values DP+思维

思路

考虑 \(dp\),类似背包。

令 \(f_{i,j}\) 表示前 \(i\) 个物品中,体积为 \(j\) 时的最大价值。

状态转移:\(f_{i,j}=max(f_{i-1,j-w_i*k_i+v_i*k_i-k_i*k_i})\)

时间复杂度为 :\(O(n^3)\) 。考虑优化,我们发现如果每个 \(w_i\) 都不相等的情况下,那么 \(w_i=1\) 时就会跑 \(W\) 次,

\(w_i=2\) 时,跑 \(W/2\) 次,这是一个调和级数,时间复杂度就是 \(O(n^2log\) \(n\)) 。

所以我们考虑把相同体积的物品进行合并考虑,令 \(g_{i,j}\) 表示体积为 \(i\) 的物品选了 \(j\) 件的最大价值,转移需要我们求出单独取物品的价值,因为取 \(k\) 个相同的物品价值为 \(v*k-k^2\)。那么取 \(k+1\) 个相同的物品价值为 \(v*(k+1)-(k+1)^2\) ,作差我们发现,比取 \(k\) 个多了 \(v-2*k-1\) 。因此这就是第 \(k+1\) 次取物品的价值。

所以,我们可以把所有体积相同的物品放到优先队列中,贪心取出最大值转移即可。

得到 \(g_{i,j}\) 后,我们就可以进行转移了。

\(f_{i,j}=max(f_{i,j},f_{i-1,j-k*i}+g_{i,k})\)

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
     int n,W;
     cin>>n>>W;
     vector<i64> v(n+1);
     vector<vector<i64>> w(W+1);
     for(int i=1;i<=n;i++){
        int x;
        cin>>x>>v[i];
        w[x].push_back(i);
     }
     vector<vector<i64>> f(W+1,vector<i64>(W+1));
     auto g=f;
     priority_queue<i64> pq;
     for(int i=1;i<=W;i++){
        int h=W/i;
        while(!pq.empty()) pq.pop();
        for(auto j:w[i]){
            pq.push(v[j]-1);
        }
        for(int j=1;j<=h;j++){
            if(pq.empty()) break;
            i64 vv=pq.top();
            pq.pop();
            g[i][j]=g[i][j-1]+vv;
            vv-=2;
            pq.push(vv);
        }
        for(int j=1;j<=W;j++){
            f[i][j]=f[i-1][j];
            for(int k=1;k<=h;k++){
                if(j<k*i) break;
                f[i][j]=max(f[i][j],f[i-1][j-k*i]+g[i][k]);
            }
            f[i][j]=max(f[i][j-1],f[i][j]);
        }
     }
     cout<<f[W][W]<<"\n";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

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

    return 0;
}

标签:Showball,AtCoder,return,Beginner,int,long,--,using,373
From: https://www.cnblogs.com/showball/p/18458437

相关文章

  • 【做题笔记】Atcoder 之 dp 专题训练
    ABCDEFGHI概率dp。设\(dp_{i,j}\)表示前\(i\)个硬币中有\(j\)个正面的概率。转移显然:\(dp_{i,j}=dp_{i-1,j-1}\timesp_i+dp_{i-1,j}\times(1-p_i)\)当\(j=0\)时,前\(i\)个硬币中没有正面。所以只能由反面的概率转移过来,转移为:\(dp_{i,j}=dp_{i-1,j}\time......
  • AtCoder Beginner Contest 374(D-E)
    A-C:惯例是宝宝题,会打暴力就能过哈D:其实也是暴力dfs,有一个double打错成int(我是猪鼻),卡了我很久#include<bits/stdc++.h>usingnamespacestd;constintmaxn=1e3+10,eps=1e-7;intn,s,t;boolvis[10];doublesum=1e8;structNode{ doublex,y,x1,y1;}a[maxn];doub......
  • キーエンスプログラミングコンテスト2024(AtCoder Beginner Contest 374)
    A.Takahashisan2判断一个字符串是否以san结尾usingnamespacereader;intmain(){strings;cin>>s;if(s[s.length()-1]=='n'ands[s.length()-2]=='a'ands[s.length()-3]=='s'){cout<<"Yes";......
  • AtCoder Beginner Contest 355
    ABC355A-WhoAtetheCake?题目传送门代码(签到题)#include<cstdio>#include<cctype>#include<cstring>#include<algorithm>usingnamespacestd;intiut(){intans=0,f=1;charc=getchar();while(!isdigit(c))f=(c=='-'......
  • AtCoder Beginner Contest 373
    ABC373A-September题目传送门代码(签到题)#include<cstdio>#include<cstring>usingnamespacestd;chars[1111];intans;intmain(){for(inti=1;i<=12;++i){scanf("%s",s+1);if(strlen(s+1)==i)++ans;}pr......
  • Solution - Atcoder ARC116C Multiple Sequences
    一个\(\mathcal{O}(m^{\frac{3}{4}}\logm)\)做法。令\(a_0=1\)。对于倍数问题,考虑类似差分的思想,定义\(b_i=\frac{a_i}{a_{i-1}}(1\lei\len)\),那么合法的\(a\)和\(b\)是双射的,就只需要考虑对\(b\)计数了。考虑到因为有\(\prod\limits_{i=1}^nb_i\lem\)......
  • abc373E How to Win the Election
    有N个候选人和总共K张选票,目前第i个候选人的票数为A[i]。在全部选票统计完成后,如果得票数多于自己的人数小于M,则当选,可以多个人同时当选。对于每个人,输出当选需要再获得的最少票数。1<=M<=N<=2E5,1<=K<=1E12,0<=A[i]<=1E12,sum(A[i])<=K分析:对每个候选人,二分答案,假设需要的票......
  • AtCoder Beginner Contest 374
    ABC374A-Takahashisan2题目传送门代码(签到题)#include<cstdio>#include<cctype>#include<cstring>#include<cmath>#include<queue>usingnamespacestd;intiut(){ intans=0,f=1;charc=getchar(); while(!isdigit(c))f=(c==&......
  • AtCoder Beginner Contest 374
    省流版A.判断末三位即可B.逐位判断即可C.枚举所有分组情况即可D.枚举线段顺序、端点顺序即可E.二分答案,发现贵的机器数量不超过\(100\),枚举求最小花费看是否可行即可F.朴素DP,复杂度分析得到有效时刻不超过\(O(n^2)\)而非\(O(s_i)\),直接\(DP\)即可A-Takahashi......
  • ABC373 E/F
    ABC373E/FE-HowtoWintheElection二分答案比较好想,可是细节有点多,复杂度$O(n\log^2n)$。一开始忘了一个特判,狂WA不止,然后调完再交,直接破防,WA一个点。接着尝试去卡,不知道怎么想的,粘错代码了。还剩半个小时,非常忙碌地调代码,但是不知道在忙什么。赛后找到正确代码,调过h......