AtCoder Beginner Contest 376

AtCoder Beginner Contest 376

\(A\) Candy Button

  • 贪心,模拟。

    点击查看代码
    int main()
    {
        ll n,c,x,last=-0x3f3f3f3f,ans=0,i;
        cin>>n>>c;
        for(i=1;i<=n;i++)
        {
            cin>>x;
            if(x-last>=c)
            {
                last=x;
                ans++;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

\(B\) Hands on Ring (Easy)

  • 每次移动都选近的一遍。正确性好像不是很显然?

    点击查看代码
    int main()
    {
        int n,q,t,ans=0,l=1,r=2,i;
        char h;
        cin>>n>>q;
        for(i=1;i<=q;i++)
        {
            cin>>h>>t;
            if(h=='L')
            {
                if(l>t)
                {
                    if(t<=r&&r<=l)	
                    {
                        ans+=n-(l-t);
                    }
                    else
                    {
                        ans+=l-t;
                    }
                    
                }
                else
                {
                    if(l<=r&&r<=t)	
                    {
                        ans+=n-(t-l);
                    }
                    else
                    {
                        ans+=t-l;
                    }
                }
                l=t;
            }
            else
            {
                if(r>t)
                {
                    if(t<=l&&l<=r)	
                    {
                        ans+=n-(r-t);
                    }
                    else
                    {
                        ans+=r-t;
                    }
                }
                else
                {
                    if(r<=l&&l<=t)	
                    {
                        ans+=n-(t-r);
                    }
                    else
                    {
                        ans+=t-r;
                    }
                }
                r=t;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

\(C\) Prepare Another Box

  • 模拟,懒得写双指针,所以用 multiset 代替了。

    点击查看代码
    ll a[200010];
    multiset<ll>f;
    multiset<ll>::iterator it;
    int main()
    {
        ll n,ans=-1,x,pos,i;
        cin>>n;
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        for(i=1;i<=n-1;i++)
        {
            cin>>x;
            f.insert(x);
        }
        sort(a+1,a+1+n);
        for(i=n;i>=1;i--)
        {
            it=f.lower_bound(a[i]);
            if(it!=f.end())
            {
                f.erase(it);
            }
            else
            {
                if(ans==-1)
                {
                    ans=a[i];
                }
                else
                {
                    ans=-1;
                    break;
                }
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

\(D\) Cycle

  • 如果是无向图(不能重复走某条边)的话,就是 暑假集训CSP提高模拟19 T2 P160. 那一天她离我而去 了。

  • 因为是有向图,所以处理出到指向 \(1\) 的节点的最短路再多走一条边即可。

    点击查看代码
    int vis[200010],dis[200010];
    vector<pair<int,int> >broke,e[200010];
    void add(int u,int v,int w)
    {
        e[u].push_back(make_pair(v,w));
    }
    void dijkstra(int s)
    {
        memset(dis,0x3f,sizeof(dis));
        memset(vis,0,sizeof(vis));
        priority_queue<pair<int,int> >q;
        dis[s]=0;
        q.push(make_pair(-dis[s],-s));
        while(q.empty()==0)
        {
            int x=-q.top().second;
            q.pop();
            if(vis[x]==0)
            {
                vis[x]=1;
                for(int i=0;i<e[x].size();i++)
                {
                    if(dis[e[x][i].first]>dis[x]+e[x][i].second)
                    {
                        dis[e[x][i].first]=dis[x]+e[x][i].second;
                        q.push(make_pair(-dis[e[x][i].first],-e[x][i].first));
                    }
                }
            }
        }
    }
    int main()
    {
        int n,m,ans=0x3f3f3f3f,u,v,w,i;
        cin>>n>>m;
        for(i=1;i<=m;i++)
        {
            cin>>u>>v;
            w=1;
            if(v==1)
            {
                broke.push_back(make_pair(u,w));
            }
            add(u,v,w);
        }
        dijkstra(1);
        for(i=0;i<broke.size();i++)
        {
            ans=min(ans,dis[broke[i].first]+broke[i].second);
        }
        cout<<((ans==0x3f3f3f3f)?-1:ans)<<endl;
        return 0;
    }
    
    

\(E\) Max × Sum

  • \(\{ a \}\) 排序后钦定选择某个数再在前缀中选前 \(k-1\) 小的数加和。

  • 优先队列维护即可。

    点击查看代码
    struct node
    {
        ll a,b;
    }e[200010];
    bool cmp(node a,node b)
    {
        return a.a<b.a;
    }
    priority_queue<ll>q;
    int main()
    {
        ll t,n,k,ans,sum,i,j;
        cin>>t;
        for(j=1;j<=t;j++)
        {
            ans=1e18;
            sum=0;
            cin>>n>>k;
            while(q.empty()==0)
            {
                q.pop();
            }
            for(i=1;i<=n;i++)
            {
                cin>>e[i].a;
            }
            for(i=1;i<=n;i++)
            {
                cin>>e[i].b;
            }
            sort(e+1,e+1+n,cmp);
            for(i=1;i<=k-1;i++)
            {
                q.push(e[i].b);
                sum+=e[i].b;
            }
            for(i=k;i<=n;i++)
            {	
                ans=min(ans,e[i].a*(sum+e[i].b));
                q.push(e[i].b);
                sum-=q.top();
                sum+=e[i].b;
                q.pop();
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    

\(F\) Hands on Ring (Hard)

  • 等有时间再来补。

\(G\) Treasure Hunting

  • 等有时间再来补。

总结

  • \(D\) 把无向图做法贺过来就直接交了,然后吃了 \(2\) 发罚时。
  • \(E\) 原权值线段树找到第 \(k-1\) 小的数然后求前缀和的做法假了,原因是若第 \(k-1\) 小的数如果有多个,就会额外统计。
posted @ 2024-10-20 07:17  hzoi_Shadow  阅读(45)  评论(0编辑  收藏  举报
扩大
缩小