AtCoder Beginner Contest 214题解

Posted 风去幽墨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 214题解相关的知识,希望对你有一定的参考价值。

D - Sum of Maximum Weights

题意:

给出一个树,包含n个节点,n-1条边,每条边有一个权重wi。记f(u,v)为点u到点v的最短路径上出现的最大的权重,求n个点两两之间的f(u,v)之和。

题解:

假设有两个树,两个树之间通过一个权重为w的边连接,且两个树中的边的权重都小于w,那么此时满足f(u,v)==w的点对个数就有size(tree1)*size(tree2) .
根据上述假设,我们可以按照边权重大小重新加边来哦构造这颗树,在构造过程中就能够得知有多少个点对是满足f(u,v)==wi的。过程中使用并查集进行合并操作。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pii pair<int,int>
#define debug(X) std::cerr<<#X<<" = "<<X<<endl
#define io_init  ios::sync_with_stdio(false);    \\
            cin.tie(0);                     \\
            cout.tie(0);
const int maxn = 2e5+5;
const int mod = 1e9+7;
int t;
int n;
int f[maxn],sz[maxn];
struct edge
{
    int u,v,w;
}e[maxn];
 
bool cmp(edge a,edge b)
{
    return a.w<b.w;
}
 
int gf(int x)
{
    return x==f[x]?x:f[x]=gf(f[x]);
}
 
int main()
{
    io_init;
    cin>>n;
    for(int i=1;i<n;++i)cin>>e[i].u>>e[i].v>>e[i].w;
    for(int i=1;i<=n;++i)f[i]=i,sz[i]=1;
    sort(e+1,e+n,cmp);
    LL ans = 0;
    for(int i=0;i<n;++i)
    {
        int x = gf(e[i].u),y=gf(e[i].v);
        ans +=1ll*e[i].w*sz[x]*sz[y];	
        //merge
        f[x]=y,sz[y]+=sz[x];
    }
    cout<<ans;
    return 0;
}

E - Packing Under Range Regulations

题意:

有n个球,每个球要求必须要放到各自的一个区间【Li,Ri】内,并且保证每个点上最多放一个球,问有没有可行的放置方法?

题解:

个人觉得是个贪心问题。

首先,假设有两个球它们对应的区间是【La,Ra】和【Lb,Rb】,其中Ra==Rb,La<Lb;那么如果想要尽可能的满足题意,应该先安排那个球呢?肯定是b球,因为即使b球安排完后【Lb,Rb】没有空余点了,那a球依然可以安排在【La,Lb-1】上。

第二,假设我们为了尽可能的满足题意,我们每次都把球放在可以放置的最小位置,这样后面的球就会有更多的选择去放,那么能够满足题意的机会也就更大一些。所以我们如果要从小王大去放置的话,就需要优先选择右端点小的球。

所以,最终我们可以将区间按照右端点递增,右端点相同时按左端点递减的顺序排列。这样能够更大机会满足题意。

代码如何记录某个点已经被占用了呢?可以使用map,因为左右端点的范围比较大,而球的个数较小。
如何知道某个点被占用后,下一个可放点在哪里呢?可以在放置球时同时记录每个点的下一个可用点。这个使用并查集能够简单有效地维护。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pii pair<int,int>
const int maxn = 2e5+5;
const int mod = 1e9+7;
int t;
int n;
map<int,int> mp;
struct edge
{
    int l,r;
}e[maxn];
 
bool cmp(edge a,edge b)
{
    if(a.r==b.r)
        return a.l>b.l;
    return a.r<b.r;
}
 
int gf(int x)
{
    return (mp.count(x)==0||mp[x]==x)?x:mp[x]=gf(mp[x]);
}
 
int main()
{
    io_init;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;++i)cin>>e[i].l>>e[i].r;
        sort(e+1,e+n+1,cmp);
        mp.clear();
        bool ok = true;
        for(int i=1;i<=n;++i)
        {
            int now = gf(e[i].l);
            if(now>e[i].r)
            {
                ok=false;
                break;
            }
            mp[now]=now+1;
        }
        if(ok)
            cout<<"Yes\\n";
        else
            cout<<"No\\n";
    }
    return 0;
}

后续若是继续补题会继续添加题解。

欢迎评论和指正!

以上是关于AtCoder Beginner Contest 214题解的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242