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
2 i ,每根电线的两个灯分别为主灯和副灯,电源从主灯来,电流向副灯。最开始有一个源点灯,所有的电源从此处流入,对于每根电线,定义其重要性为 :切断这根电线后不能通电的所有灯的亮度之和。首先题目按电线的重要性给出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 ( ) ;
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;
}