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 115 题解