2024.7.25模拟赛7
1.2024.7.18模拟赛12.2024.7.19模拟赛23.2024.7.20模拟赛34.2024.7.21模拟赛45.2024.7.22模拟赛56.2024.7.23 模拟赛6
7.2024.7.25模拟赛7
8.2024.7.26模拟赛89.2024.7.27模拟赛910.2024.7.28 模拟赛1011.2024.7.29模拟赛1112.2024.7.31模拟赛1213.2024.8.1 模拟赛1314.2024.8.6 模拟赛 1415.2024.8.7 模拟赛 1516.2024.8.8模拟赛1617.2024.8.10模拟赛1718.2024.8.18 模拟赛 2219.2024.8.19 模拟赛 2420.小集训21.2024.9.23 模拟赛 CSP 322.2024.9.24 模拟赛 CSP423.2024.9.25 模拟赛 多校24.2024.9.27 模拟赛 CSP525.2024.9.28 模拟赛 CSP626.2024.9.30 模拟赛 CSP727.2024.10.7 模拟赛 多校328.2024.?.?? 模拟赛 ???模拟赛
疯狂补题解/改题中。。。
T1 [Permutations & Primes] (未找到)
构造一个
的序列,使所有区间中 为质数的最多。
感觉题不是很好。结论是:
打标找规律,感性证明也挺显然的。
no code
T2 Spread of Information
首先看道典题:消防局的设立
题很水,但是思路一样,半径为
采用贪心的策略,每次找到没有被覆盖的最深的点,向上跳
但是这道题暴跳肯定不行,因为跳跃过程中要更新最小距离,倍增也不太好搞。
所以我们稍微变一下思路,还是跳祖先,跳到祖先直接 dfs 把能覆盖的点都标记。这样被标记的点一定不会再被跳。
虽然看着很暴力,但真的很快,而且卡不掉?
code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int n,k,a[N],dep[N],fa[N];
int head[N],tot;
struct E {int u,v;} e[N<<1];
inline void add(int u,int v) {e[++tot]={head[u],v}; head[u]=tot;}
inline int qr()
{
char ch=getchar();int x=0,f=1;
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
inline void dfs(int u,int f)
{
dep[u]=dep[f]+1; a[u]=u; fa[u]=f;
for(int i=head[u];i;i=e[i].u)
{
int v=e[i].v;
if(v==f) continue;
dfs(v,u);
}
}
inline bool cmp(int x,int y) {return dep[x]>dep[y];}
bool vs[N];
inline void fg(int u,int f,int d,int mid)
{
if(d>mid) return;
vs[u]=1;
for(int i=head[u];i;i=e[i].u)
{
int v=e[i].v;
if(v==f) continue;
fg(v,u,d+1,mid);
}
}
inline bool check(int mid)
{
int res=0;
for(int i=1;i<=n;i++) vs[i]=0;
for(int i=1;i<=n;i++) if(!vs[a[i]])
{
int u=a[i],jp=mid;
while(fa[u]&&jp) u=fa[u],jp--;
fg(u,0,0,mid);
res++;
if(res>k) return 0;
}
return 1;
}
int main()
{
n=qr(); k=qr();
for(int i=1;i<n;i++)
{
int x=qr(),y=qr();
add(x,y); add(y,x);
}
dfs(1,0);
sort(a+1,a+1+n,cmp);
int l=1,r=dep[a[1]],ans=r;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
return 0;
}
还可以倍增优化一下暴跳,好像变慢了。
倍增code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int n,k,a[N],dep[N],fa[20][N],lg;
int head[N],tot;
struct E {int u,v;} e[N<<1];
inline void add(int u,int v) {e[++tot]={head[u],v}; head[u]=tot;}
inline int qr()
{
char ch=getchar();int x=0,f=1;
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
inline void dfs(int u,int f)
{
dep[u]=dep[f]+1; a[u]=u; fa[0][u]=f;
for(int i=1;i<=lg;i++) fa[i][u]=fa[i-1][fa[i-1][u]];
for(int i=head[u];i;i=e[i].u)
{
int v=e[i].v;
if(v==f) continue;
dfs(v,u);
}
}
inline bool cmp(int x,int y) {return dep[x]>dep[y];}
bool vs[N];
inline void fg(int u,int f,int d,int mid)
{
if(d>mid) return;
vs[u]=1;
for(int i=head[u];i;i=e[i].u)
{
int v=e[i].v;
if(v==f) continue;
fg(v,u,d+1,mid);
}
}
inline bool check(int mid)
{
int res=0;
for(int i=1;i<=n;i++) vs[i]=0;
for(int i=1;i<=n;i++) if(!vs[a[i]])
{
int u=a[i];
for(int j=lg;j>=0;j--) if(fa[j][u]&&dep[fa[j][u]]>=dep[a[i]]-mid) u=fa[j][u];
fg(u,0,0,mid);
res++;
if(res>k) return 0;
}
return 1;
}
int main()
{
// freopen("in.in","r",stdin);
n=qr(); k=qr(); lg=__lg(n);
for(int i=1;i<n;i++)
{
int x=qr(),y=qr();
add(x,y); add(y,x);
}
dfs(1,0);
sort(a+1,a+1+n,cmp);
int l=1,r=dep[a[1]],ans=r;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
return 0;
}
T3 Ball Collector
一开始想二分图,树上遍历同时跑匈牙利。后来 GGrun 证明可以,HACK 之后
其实思路还是类似的,将同一个节点的两个颜色连边。
观察得性质,每选一个节点的颜色就相当于选一条边,如果边数大于颜色点数,那么一定可以选中所有颜色。否则有多少条边就能选多少种颜色。
因此对于我们以颜色为点建的图中,答案就是
然后考虑实时维护这个图。用到新科技:可撤销并查集。
其实原理很简单,就是在树上递归到一个点时记录这个状态,回溯时把它回归这个状态。
查询时不能路径压缩,合并时需要按秩合并(类似启发式合并,浅的合并到深的里,本题
好像挺简单的?
code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int n,ans[N],res,a[N],b[N],fa[N],sz[N],ed[N];
int head[N],tot;
struct E {int u,v;} e[N<<1];
inline void add(int u,int v) {e[++tot]={head[u],v}; head[u]=tot;}
int find(int x) {return fa[x]==x?x:find(fa[x]);}
struct A {int x,fa,sz,e;} g[N];
void merge(int u,int v,stack<A> &st,int &ans)
{
u=find(u); v=find(v);
st.push(A{u,fa[u],sz[u],ed[u]});
st.push(A{v,fa[v],sz[v],ed[v]});
if(u==v)
{
ed[u]++;
if(ed[u]==sz[u]) res++;
return;
}
if(sz[u]<sz[v]) swap(u,v);
ans-=min(sz[u],ed[u]); res-=min(sz[v],ed[v]);
fa[v]=u; sz[u]+=sz[v]; ed[u]+=ed[v]+1;
ans+=min(sz[u],ed[u]);
}
void dfs(int u,int f)
{
stack<A> st; int tmp=res;
merge(a[u],b[u],st,res);
ans[u]=res;
for(int i=head[u];i;i=e[i].u)
{
int v=e[i].v;
if(v==f) continue;
dfs(v,u);
}
while(!st.empty())
{
A pre=st.top(); st.pop();
fa[pre.x]=pre.fa;
sz[pre.x]=pre.sz;
ed[pre.x]=pre.e;
}
res=tmp;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
for(int i=1;i<n;i++)
{
int x,y; scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
for(int i=1;i<=n;i++) fa[i]=i,sz[i]=1,ed[i]=0;
dfs(1,0);
for(int i=2;i<=n;i++) printf("%d ",ans[i]);
return 0;
}
T4 Joker
先挂张图,咕咕咕。。。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端