绵阳东辰国际test2019.10.31
吐槽:当时脑抽了,总是往难得地方想,实际上很简单一道签到题,总结以后要求自己第一题代码不能超过50行,不然就不要写(肯定就是方法错了)
分析:构造的时候就每次在它前面从大到小的放,这样保证肯定能消完的
code :
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int a[300005],ans[300005];
int n1;
int c;
int main(){
scanf("%d%d%d",&n,&m,&k);
c=n-k;
for(int i=1;i<=k;i++)scanf("%d",&a[i]);
for(int i=1;i<=k;i++){
for(int j=m;j>a[i]&&c;j--)ans[++n1]=j,c--;
ans[++n1]=a[i];
}
if(n1!=n)printf("No");
else{
printf("Yes\n");
for(int i=1;i<=n;i++)printf("%d ",ans[i]);
}
return 0;
}
吐槽:n3log暴力炸了?,我真的是服了我自己了,代码功底太好了
这题数据用脚造的,暴力能过,这样这道题就毫无意义了
我们考虑一个显然的贪心:将所有没有连接的边放入一个堆中,并按照度数之和
从大到小进行排序。然后每次选出度数和最大的那个,把它们连起来,并将所有度数
和变化的点相邻的边重新加入堆中,重复上述过程
正解是n3的
但是事实上,注意到度数和不超过 2n,所以我们可以将堆换为 2n 个队列。
每次如果新加入的边度数和 ≥ K,那么我们就把他们直接连起来,否则加入对应和的队列中。
那么因为这样只有 < K 的队列会新增元素,所以我们每次考虑将 K 减少 1 之
后得到的队列并加入即可
code:
#include<bits/stdc++.h>
using namespace std;
#define CO const
#define IN inline
typedef long long LL;
template<class T> T read(){
T x=0,w=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*w;
}
template<class T> IN T read(T&x){
return x=read<T>();
}
int n;
int ans,rem,deg[501];
bool vis[501][501];
vector<pair<int,int> > vec[1001];
extern void extend(int u,int v);
void add(int u,int v){
if(vis[u][v]) return;
vis[u][v]=1,--rem;
++deg[u],++deg[v];
for(int i=1;i<=n;++i){
if(i!=u) extend(i,u);
if(i!=v) extend(i,v);
}
}
void extend(int u,int v){
if(u>v) swap(u,v);
if(deg[u]+deg[v]>=ans) add(u,v);
else vec[deg[u]+deg[v]].push_back(make_pair(u,v));
}
int main(){
read(n);
int m=read<int>();
for(int i=1;i<=m;++i){
int u=read<int>(),v=read<int>();
if(u>v) swap(u,v);
vis[u][v]=1;
++deg[u],++deg[v];
}
ans=2*n,rem=n*(n-1)/2-m;
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j) extend(i,j);
while(rem){
while(ans and vec[ans].empty()) ans--;
add(vec[ans].back().first,vec[ans].back().second);
vec[ans].pop_back();
}
printf("%d\n",ans);
return 0;
}
T3考试的时候没看,讲课的时候在睡觉,于是就跳过吧