首页 > 其他分享 >Panasonic Programming Contest 2024(AtCoder Beginner Contest 375)

Panasonic Programming Contest 2024(AtCoder Beginner Contest 375)

时间:2024-10-13 08:51:35浏览次数:1  
标签:AtCoder Beginner Contest int ll min 200010 vis dis

Panasonic Programming Contest 2024(AtCoder Beginner Contest 375)

\(A\) Seats \(AC\)

  • 基础字符串。

    点击查看代码
    int main()
    {
        int n,ans=0,i;
        string s;
        cin>>n>>s;
        for(i=0;i<n;i++)
        {
            ans+=(s[i]=='#'&&s[i+1]=='.'&&s[i+2]=='#'&&i+2<n);
        }
        cout<<ans<<endl;
        return 0;
    }
    

\(B\) Traveling Takahashi Problem \(AC\)

  • 循环结构。

    点击查看代码
    double x[200010],y[200010];
    int main()
    {
        int n,i;
        double ans=0;
        cin>>n;
        for(i=1;i<=n;i++)
        {
            cin>>x[i]>>y[i];
            ans+=sqrt((x[i]-x[i-1])*(x[i]-x[i-1])+(y[i]-y[i-1])*(y[i]-y[i-1]));
        }
        ans+=sqrt(x[n]*x[n]+y[n]*y[n]);
        printf("%.12lf",ans);
        return 0;
    }
    

\(C\) Spiral Rotation

  • 暂且先不管 \(x,y \in [i,n+1-i]\) 的限制,手摸一下替换过程,发现循环节长度为 \(4\) 。

    • \((x,y) \to (y,n+1-x) \to (n+1-x,n+1-y) \to (n+1-y,x) \to (x,y) \to \dots\)
  • 若 \(x,y \in [i,n+1-i]\) 相应地有 \(n+1-y,n+1-x \in [i,n+1-i]\) 。

  • 又因为使得 \(x,y \in [i,n+1-i]\) 的最大的 \(i\) 等于 \(\min(x,y,n+1-x,n+1-y)\) ,处理出 \((x,y)\) 最终能替换的位置即可。

    点击查看代码
    char a[3010][3010],b[3010][3010];
    int main()
    {
        int n,x,y,nx,ny,i;
        cin>>n;
        for(x=1;x<=n;x++)
        {
            for(y=1;y<=n;y++)
            {
                cin>>a[x][y];
            }
        }
        for(x=1;x<=n;x++)
        {
            for(y=1;y<=n;y++)
            {
                nx=x;
                ny=y;
                for(i=1;i<=min({x,y,n+1-x,n+1-y})%4;i++)
                {
                    swap(nx,ny);
                    ny=n+1-ny;
                }
                b[nx][ny]=a[x][y];
            }
        }
        for(x=1;x<=n;x++)
        {
            for(y=1;y<=n;y++)
            {
                cout<<b[x][y];
            }
            cout<<endl;
        }
        return 0;
    }
    

\(D\) ABA \(AC\)

  • 考虑枚举 \(i,k\) ,那么任意的 \(j \in (i,k)\) 都合法,统计一下贡献即可。

    点击查看代码
    string s;
    vector<int>pos[30];
    int main()
    {
        ll ans=0,i,j,k;
        cin>>s;
        for(i=0;i<s.size();i++)
        {
            pos[s[i]-'A'+1].push_back(i+1);
        }
        for(i=1;i<=26;i++)
        {
            if(pos[i].size()>=2)
            {
                ans-=(pos[i].size()-1)*pos[i].size()/2;
                for(j=0;j<pos[i].size();j++)
                {
                    ans+=(j+j+1-(ll)pos[i].size())*pos[i][j];
                }
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

\(E\) 3 Team Division \(AC\)

  • 观察到 \(\sum\limits_{i=1}^{n}b_{i} \le 1500\) ,考虑暴力 \(DP\) 。

  • 设 \(f_{i,j,k,h}\) 表示处理到第 \(i\) 个人使得第 \(1,2,3\) 组的力量分别为 \(j,k,h\) 最少移动人的次数。

  • 压缩 \(j+k+h=\sum\limits_{i=1}^{n}b_{i}\) 加滚动数组后即可通过。

    点击查看代码
    int a[110],b[110],sum[4],f[2][3010][3010];
    int main()
    {
        int n,num=0,i,j,k;
        cin>>n;
        for(i=1;i<=n;i++)
        {
            cin>>a[i]>>b[i];
            sum[a[i]]+=b[i];
            num+=b[i];
        }
        if(num%3==0)
        {
            memset(f,0x3f,sizeof(f));
            f[0][sum[1]][sum[2]]=0;
            for(i=1;i<=n;i++)
            {   
                if(a[i]==1)
                {
                    for(j=0;j<=num;j++)
                    {
                        for(k=0;k<=num;k++)
                        {
                            f[i&1][j][k]=f[(i-1)&1][j][k];
                            if(k-b[i]>=0)
                            {
                                f[i&1][j][k]=min(f[i&1][j][k],f[(i-1)&1][j+b[i]][k-b[i]]+1);
                            }
                            if(num-j-k-b[i]>=0)
                            {
                                f[i&1][j][k]=min(f[i&1][j][k],f[(i-1)&1][j+b[i]][k]+1);
                            }
                        }
                    }
                }
                if(a[i]==2)
                {
                    for(j=0;j<=num;j++)
                    {
                        for(k=0;k<=num;k++)
                        {
                            f[i&1][j][k]=f[(i-1)&1][j][k];
                            if(j-b[i]>=0)
                            {
                                f[i&1][j][k]=min(f[i&1][j][k],f[(i-1)&1][j-b[i]][k+b[i]]+1);
                            }
                            if(num-j-k-b[i]>=0)
                            {
                                f[i&1][j][k]=min(f[i&1][j][k],f[(i-1)&1][j][k+b[i]]+1);
                            }
                        }
                    }
                }
                if(a[i]==3)
                {
                    for(j=0;j<=num;j++)
                    {
                        for(k=0;k<=num;k++)
                        {
                            f[i&1][j][k]=f[(i-1)&1][j][k];
                            if(j-b[i]>=0)
                            {
                                f[i&1][j][k]=min(f[i&1][j][k],f[(i-1)&1][j-b[i]][k]+1);
                            }
                            if(k-b[i]>=0)
                            {
                                f[i&1][j][k]=min(f[i&1][j][k],f[(i-1)&1][j][k-b[i]]+1);
                            }
                        }
                    }
                }
            }
            if(f[n&1][num/3][num/3]==0x3f3f3f3f)
            {
                cout<<-1<<endl;
            }
            else
            {
                cout<<f[n&1][num/3][num/3]<<endl;
            }
        }
        else
        {
            cout<<-1<<endl;
        }
        return 0;
    }
    

\(F\) Road Blocked

  • 删边最短路不会写,遂考虑倒序加边。

  • 观察到至多删除 \(300\) 条边,而 \(Floyd\) 每次加入一条边更新最短路的时间复杂度为 \(O(n^{2})\) ,可以通过。

    • 每加入一条边只有以这条边的两个端点作为中转点的最短路会得到更新,故时间复杂度为 \(O(n^{2})\) 。
    点击查看代码
    ll dis[310][310],pd[200010],x[200010],y[200010],u[200010],v[200010],w[200010],vis[200010],ans[200010];
    int main()
    {
        ll n,m,q,i,j,k;
        cin>>n>>m>>q;
        for(i=1;i<=m;i++)
        {
            cin>>u[i]>>v[i]>>w[i];
        }
        for(i=1;i<=q;i++)
        {
            cin>>pd[i]>>x[i];
            if(pd[i]==1)
            {
                vis[x[i]]=1;
            }
            else
            {
                cin>>y[i];
            }
        }
        memset(dis,0x3f,sizeof(dis));
        for(i=1;i<=m;i++)
        {
            if(vis[i]==0)
            {
                dis[u[i]][v[i]]=dis[v[i]][u[i]]=min(dis[u[i]][v[i]],w[i]);
            }
        }
        for(k=1;k<=n;k++)
        {
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=n;j++)
                {
                    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
                }
            }
        }
        for(k=q;k>=1;k--)
        {
            if(pd[k]==1)
            {
                dis[u[x[k]]][v[x[k]]]=dis[v[x[k]]][u[x[k]]]=min(dis[u[x[k]]][v[x[k]]],w[x[k]]);
                for(i=1;i<=n;i++)
                {
                    for(j=1;j<=n;j++)
                    {
                        dis[i][j]=min(dis[i][j],dis[i][u[x[k]]]+dis[u[x[k]]][j]);
                    }
                }
                for(i=1;i<=n;i++)
                {
                    for(j=1;j<=n;j++)
                    {
                        dis[i][j]=min(dis[i][j],dis[i][v[x[k]]]+dis[v[x[k]]][j]);
                    }
                }
            }
            else
            {
                ans[k]=dis[x[k]][y[k]];
            }
        }
        for(i=1;i<=q;i++)
        {
            if(pd[i]==2)
            {
                cout<<((ans[i]==0x3f3f3f3f3f3f3f3f)?-1:ans[i])<<endl;
            }
        }
        return 0;
    }
    

\(G\) Road Blocked 2

  • 考虑建出从 \(1 \sim n\) 的最短路 \(DAG\) ,然后等价于询问这个 \(DAG\) 上的必经边,当无向图处理出割边即可。

    点击查看代码
    struct node
    {
        ll nxt,to,w,id;
    }e[400010];
    ll head[400010],dis[400010],vis[400010],cut[400010],dfn[400010],low[400010],cnt=0,tot=0;
    vector<pair<ll,ll> >pre[400010],E[400010];
    void add(ll u,ll v,ll w,ll id)
    {
        cnt++;
        e[cnt].nxt=head[u];
        e[cnt].to=v;
        e[cnt].w=w;
        e[cnt].id=id;
        head[u]=cnt;
    }
    void dijkstra(ll s)
    {
        memset(dis,0x3f,sizeof(dis));
        memset(vis,0,sizeof(vis));  
        priority_queue<pair<ll,ll> >q;
        dis[s]=0;
        q.push(make_pair(-dis[s],s));
        while(q.empty()==0)
        {
            ll x=q.top().second;
            q.pop();
            if(vis[x]==0)
            {
                vis[x]=1;
                for(ll i=head[x];i!=0;i=e[i].nxt)
                {
                    if(dis[e[i].to]>dis[x]+e[i].w)
                    {
                        dis[e[i].to]=dis[x]+e[i].w;
                        q.push(make_pair(-dis[e[i].to],e[i].to));
                    }
                }
            }
        }
    }
    void build(ll n)
    {
        for(ll x=1;x<=n;x++)
        {
            for(ll i=head[x];i!=0;i=e[i].nxt)
            {
                if(dis[e[i].to]==dis[x]+e[i].w)
                {
                    pre[e[i].to].push_back(make_pair(x,e[i].id));
                }
            }
        }
    }
    void dfs(ll x)
    {
        if(vis[x]==0)
        {
            vis[x]=1;
            for(ll i=0;i<pre[x].size();i++)
            {
                dfs(pre[x][i].first);
                E[pre[x][i].first].push_back(make_pair(x,pre[x][i].second));
                E[x].push_back(make_pair(pre[x][i].first,pre[x][i].second));
            }
        }
    }
    void tarjan(ll x,ll fa)
    {
        ll flag=0;
        tot++;
        dfn[x]=low[x]=tot;
        for(ll i=0;i<E[x].size();i++)
        {
            if(dfn[E[x][i].first]==0)
            {
                tarjan(E[x][i].first,x);
                low[x]=min(low[x],low[E[x][i].first]);
                if(low[E[x][i].first]>dfn[x])
                {
                    cut[E[x][i].second]=1;
                }
            }
            else
            {
                if(E[x][i].first==fa&&flag==0)
                {
                    flag=1;
                }
                else
                {
                    low[x]=min(low[x],dfn[E[x][i].first]);
                }
            }
        }
    }
    int main()
    {
        ll n,m,u,v,w,i;
        cin>>n>>m;
        for(i=1;i<=m;i++)
        {
            cin>>u>>v>>w;
            add(u,v,w,i);
            add(v,u,w,i);
        }
        dijkstra(1);
        build(n);
        memset(vis,0,sizeof(vis));
        dfs(n);
        tarjan(1,1);
        for(i=1;i<=m;i++)
        {
            if(cut[i]==0)
            {
                cout<<"No"<<endl;
            }
            else
            {
                cout<<"Yes"<<endl;
            }
        }
        return 0;
    }
    

总结

  • 误认为 \(AT\) 加火车头后就能跑得飞快,致使 \(C,D\) 先交了一发暴力,然后就吃罚时了。
  • \(E\) 数组开小了,吃了一发罚时。
  • \(G\) 最后 \(30 \min\) 开始码,写完后发现不会求 \(1 \sim n\) 的最短路 \(DAG\) ,只胡了个建出全图的最短路 \(DAG\) 再从 \(n\) 倒着建回来。比赛结束时也没有调完。

标签:AtCoder,Beginner,Contest,int,ll,min,200010,vis,dis
From: https://www.cnblogs.com/The-Shadow-Dragon/p/18461845

相关文章

  • AtCoder Beginner Contest 375
    省流版A.枚举所有子串判断即可B.模拟计算记录累加即可C.根据旋转的周期性对每个点旋转次数取模后暴力旋转即可D.枚举\(k\),考虑\(i,j\)的对数,写成数学表达式后维护个数和位置和即可E.背包问题,以前两个数组和为状态,考虑每个数移动到何处转移即可F.逆向,删边变加边,维护......
  • KEYENCE Programming Contest 2024(AtCoder Beginner Contest 374)E题
    六年级蒟蒻来题解了!!!题目大意:给定你一个n,表示有n个生产线,每一个生产线都有两种机器,第i个生产线第一件产品每天可以造Ai件零件但是得付出Pi元的代价,第二件产品每天可以生产Bi件物品但是得付出Qi元的代价,然后给你x元的预算问你所有流水线中的最小值的最大值是多少?思路:首先我们......
  • 2023 Benelux Algorithm Programming Contest (BAPC 23)
    A-\texttt题意\(n\)个软件包,已知大小,可以同时下载\(k\)个,已经下载好了\(m\)个,选\(k\)个下载使得下载完后进度最大,输出已完成进度所占百分比。思路选最大的\(m+k\)个。代码点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvoid......
  • The 2022 ICPC Asia Hangzhou Regional Programming Contest K. Master of Both
    题目链接题意:给定n个字符串,然后给定q种字典序规则,在这q种字典序规则下求出这n个字符串的逆序对数量。思路:我们发现q很大,对于每一种排序规则都遍历一遍n个字符串去求逆序对的数量复杂度太高,所以考虑预处理。我们知道要判断两个字符串字典序的大小关系,只需要知道它们第......
  • AtCoder Beginner Contest 373 (A-F)
    AtCoderBeginnerContest373(A-F)比赛链接A-September#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;voidShowball(){intans=0;for(inti=1;i<=12;i++){strings;cin>>s;ans+=((int)s.si......
  • The 2021 ICPC Asia Shenyang Regional Contest
    目录写在前面E签到F签到JBFSB带权并查集H图论I数学L树形DP,容斥M字符串,离线,单调性G贪心写在最后写在前面比赛地址:https://codeforces.com/gym/103427。以下按个人向难度排序。唉唉国庆vp三场唯一打的还像人的一场,最后手里还有两道题在写可惜都没出来呃呃。被树上背......
  • 【做题笔记】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......
  • The 2023 ICPC Asia Hangzhou Regional Contest (The 2nd Universal Cup. Stage 22: H
    The2023ICPCAsiaHangzhouRegionalContest(The2ndUniversalCup.Stage22:Hangzhou)M.V-Diagram题意:给定一个“v图”,求平均值最大的子"v图"思路:原图的最低点以及左右两个点必须取,如何先取满左边或者右边在贪心即可voidsolve(){lln;cin>>n;vect......
  • 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";......