10/12:牛客 tg 第不知道多少场
模拟赛次次垫底,是不是该尽早退役?
A
显然排序后选相邻两个来组合最优,设 表示前 个元素组 队的最小值。
写nm贪心活该挂大分
B
首先对于没有 的情况, 且满足 最小肯定要删去 。
再讨论存在 的情况,可以用 先维护准备填的数(也没必要吧)。
若 则考虑当前填的数 和后面最小的数 ,若 则显然把 删了填给 优。
再者,若 ,考虑 填的数,对于 和 根据没有 的情况判断就行了。
int n,a[N],minn[N];
set<int>st;
void solve(){
scanf("%d",&n);
st.clear();
for(int i=1;i<=n;++i)st.insert(i);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
if(a[i])st.erase(a[i]);
}minn[n+1]=a[n+1]=n+1;
for(int i=n;i;--i){
if(a[i]&&a[i]<a[minn[i+1]])minn[i]=i;
else minn[i]=minn[i+1];
}
for(int i=1;i<=n;++i){
if(i==n){a[i]=-1;break;}
if(a[i]&&a[i+1]&&a[i]>a[i+1]){a[i]=-1;break;}
if(!a[i]){
int qwq=*st.begin();
if(a[minn[i]]<qwq){a[minn[i]]=-1;break;}
}else if(!a[i+1]){
int qwq=*st.begin();
if(a[i]>qwq){a[i]=-1;break;}
}
if(!a[i])st.erase(st.begin());
}
st.clear();
for(int i=1;i<=n;++i)st.insert(i);
for(int i=1;i<=n;++i){
if(!a[i]||a[i]==-1)continue;
st.erase(a[i]);
}
for(int i=1;i<=n;++i){
if(a[i]==-1)continue;
if(a[i])printf("%d ",a[i]);
else printf("%d ",*st.begin()),st.erase(st.begin());
}printf("\n");
}
C
点集在树上的斯坦纳树即为其虚树。
该算法是正确的,当且仅当给定点集 在 上的虚树点
集 和 相同。
因为如果有其他的虚点的话则必然有边多算了一次。
关于如何维护虚点:可以考虑倒着做,每次删去一个点。如果删去的这个点
有三条及以上的边相连,它就转型成为虚点。如果某次删除后,某个虚点只有
两条边相连,则该虚点消失。答案为 当且仅当不存在虚点时。
对于边权存在 的情况,只需要将所有由 边连结的连通块视为一个点,一
个连通块被选中当且仅当其中至少有一个点被选中,然后应用上述做法即可。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
const int N=3e5+10;
int n,p[N],cnt[N];
int sum=0,ans[N];
set<int>e[N];//学到了用set维护边,方便删除
struct node{int u,v,w;}edge[N];
#define add(x,y) e[x].insert(y)
#define del(x,y) e[x].erase(y)
int fa[N];
int fnd(int x){return x!=fa[x]?fa[x]=fnd(fa[x]):x;}
void Del(int x){
if(e[x].size()>2||cnt[x]>0)return;
--sum;
int tmp[3],cnt=0;
for(int v:e[x])tmp[++cnt]=v;
e[x].clear();
for(int i=1;i<=cnt;++i){
for(int j=1;j<=cnt;++j){
if(i==j)continue;
add(tmp[i],tmp[j]);
}
del(tmp[i],x);
}
for(int i=1;i<=cnt;++i)Del(tmp[i]);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)fa[i]=i;
for(int i=1;i<n;++i){
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
if(!edge[i].w)fa[fnd(edge[i].u)]=fnd(edge[i].v);
}
for(int i=1;i<n;++i)if(edge[i].w)add(fnd(edge[i].u),fnd(edge[i].v)),add(fnd(edge[i].v),fnd(edge[i].u));
for(int i=1;i<=n;++i)scanf("%d",&p[i]),++cnt[fnd(p[i])];
for(int i=n;i;--i){
ans[i]=!sum;
if(!--cnt[fnd(p[i])])++sum,Del(fnd(p[i]));
}
for(int i=1;i<=n;++i)printf("%d",ans[i]);
return 0;
}
D
心累,不想补了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】