Codeforces Round #611 (Div. 3)

Codeforces Round #611 (Div. 3)

D题:

题意:给出n个点,让找出m个点和这n个点不同的点,使得他们的距离最小。并输出他们。

题解:我们直接找n个点相邻的点先放进队列中作为下一个试探点,然后BFS查找。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+7;
map<int,int> vis;
int arr[N];
queue<pair<int,int> > q;
signed main()
{
	int n,m; cin>>n>>m;
	for(int i=1;i<=n;i++){
		scanf("%lld",&arr[i]);
		vis[arr[i]]=1;
	}
	for(int i=1;i<=n;i++){
		if(!vis[arr[i]+1]){
			q.push(make_pair(arr[i]+1,1));
			vis[arr[i]+1]=1;
		}
		if(!vis[arr[i]-1]){
			q.push(make_pair(arr[i]-1,1));
			vis[arr[i]-1]=1;
		}
	}
	vector<int> ans;
	int res=0;
	while(ans.size()<m){
		pair<int,int> u=q.front();
		ans.push_back(u.first);
		q.pop();
		res+=u.second;
		if(!vis[u.first+1]){
			q.push(make_pair(u.first+1,u.second+1));
			vis[u.first+1]=1;
		}
		if(!vis[u.first-1]){
			q.push(make_pair(u.first-1,u.second+1));
			vis[u.first-1]=1;
		}
	}
	cout<<res<<endl;
	for(int i=0;i<m;i++) cout<<ans[i]<<' ';
}

E题:

题意:给n个人的居住房子的坐标,他们可以左右移动。问最少居住的房子,和最多居住的房子。

题解:暴力贪心跑一下就可以了。但是这道题不能跑一个点如果大于2就左右加加,他可能存在这个地方两个人,右边没人,这样的话就没人过去了。跑回来也是同理。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+7;
int pos[N],pos1[N];
signed main()
{
	int n; cin>>n;
	for(int i=1;i<=n;i++){
		int x; scanf("%lld",&x);
		pos[x]++,pos1[x]++;
	}
	for(int i=n+1;i>=0;i--){
		if(pos[i]>1){
			pos[i-1]++;
			pos[i]--;
		}
	}
	for(int i=0;i<=n+1;i++){
		if(pos[i]>1){
			pos[i+1]++;
			pos[i]--;
		}
	}
	int res=0,res2=0;
	for(int i=0;i<=n+1;i++) if(pos[i]) res++;
	for(int i=0;i<=n+1;){
		if(pos1[i]) res2++,i+=3;
		else i++;
	}
	cout<<res2<<' '<<res<<endl;
}

F题:

题意:一根电线连接着两个点,这两个点分别代表着两个灯,灯有自己的编号i,其亮度是 2 i 2^i 2i,每根电线的两个灯分别为主灯和副灯,电源从主灯来,电流向副灯。最开始有一个源点灯,所有的电源从此处流入,对于每根电线,定义其重要性为 :切断这根电线后不能通电的所有灯的亮度之和。首先题目按电线的重要性给出n-1条电线的主灯编号,让你重要性从大到小输出每条电线所连接的两个灯的序号(无前后差别)。

题解:首先我们知道,他在输入的时候就按照重要性大的输入,那么第一个一定是我们的源点(因为我们是一个树形结构),我们输入的时候顺便记录下我们各个节点的度,我们知道我们的叶子节点一定不可能是主灯,所以我们输入后我们把叶子节点放进优先队列中,我们最顶上的节点和我们最不重要的节点先连接起来(根据题意),连一次我们节点的度数减少,然后如果为0则加入进我们的优先队列中。然后这样找出n-1条边出来。(树形结构很重要!!)

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int in[N];
vector<int> to;
int main(){
	int n,regin=-1; 
	cin>>n;
	priority_queue<int,vector<int> ,greater<int> > q;
	for(int i=1;i<n;i++){
		int tmp; cin>>tmp;
		if(regin==-1) regin=tmp;
		in[tmp]++;
		to.push_back(tmp);
	}
	for(int i=1;i<=n;i++){
		if(!in[i]) q.push(i);
	}
	vector<pair<int,int> >edge;
	while(!q.empty()){
		int u=q.top(); q.pop();
//		cout<<"---"<<u<<endl;
		edge.push_back(make_pair(u,to[to.size()-1]));
		in[to[to.size()-1]]--;
		if(edge.size()==n-1) break;
		if(in[to[to.size()-1]]==0) q.push(to[to.size()-1]);
		to.pop_back();
	}
	cout<<regin<<endl;
	for(int i=edge.size()-1;i>=0;i--) cout<<edge[i].first<<' '<<edge[i].second<<endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值