2025多校冲刺省选模拟赛8
2025多校冲刺省选模拟赛8
A. 波斯菊
-
每个连通块内以关键点为起点的最长路径
相互独立,有 即为所求。 -
观察到可以直接钦定每个关键点距离其最远的点的是哪个点,这样的话就只需要任意两个路径不相交就能保证一定存在一种划分方案合法。
-
设
分别表示以 为根的子树内只有一个起点在往上走/只有一个终点在往上走(不一定要被匹配到)/没有点在往上走的答案。 -
转移时考虑从两棵子树内的节点转移而来,特殊处理关键点处的转移。
点击查看代码
struct node { ll nxt,to; }e[1000010]; ll head[500010],vis[500010],f[3][500010],cnt=0; void add(ll u,ll v) { cnt++; e[cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt; } void dfs(ll x,ll fa) { ll maxx,sum=0,u=-0x3f3f3f3f3f3f3f3f,v=-0x3f3f3f3f3f3f3f3f; for(ll i=head[x];i!=0;i=e[i].nxt) { if(e[i].to!=fa) { dfs(e[i].to,x); sum+=max(f[1][e[i].to],f[2][e[i].to]); } } if(vis[x]==1) { f[1][x]=sum; for(ll i=head[x];i!=0;i=e[i].nxt) { if(e[i].to!=fa) { f[0][x]=max(f[0][x],sum-max(f[1][e[i].to],f[2][e[i].to])+f[0][e[i].to]); f[2][x]=max(f[2][x],sum-max(f[1][e[i].to],f[2][e[i].to])+f[0][e[i].to]); } } } else { f[0][x]=1; f[1][x]=-0x3f3f3f3f3f3f3f3f; f[2][x]=sum; for(ll i=head[x];i!=0;i=e[i].nxt) { if(e[i].to!=fa) { maxx=max(f[1][e[i].to],f[2][e[i].to]); f[0][x]=max(f[0][x],sum-maxx+f[0][e[i].to]+1); f[1][x]=max(f[1][x],sum-maxx+f[1][e[i].to]+1); f[2][x]=max({f[2][x],sum-maxx+f[1][e[i].to]+1+u,sum-maxx+f[0][e[i].to]+1+v}); u=max(u,f[0][e[i].to]-maxx); v=max(v,f[1][e[i].to]-maxx); } } } } int main() { #define Isaac #ifdef Isaac freopen("coreopsis.in","r",stdin); freopen("coreopsis.out","w",stdout); #endif ll n,k,x,u,v,i; cin>>n>>k; for(i=1;i<=k;i++) { cin>>x; vis[x]=1; } for(i=1;i<=n-1;i++) { cin>>u>>v; add(u,v); add(v,u); } dfs(x,0); cout<<2*n-2*k-max({f[0][x],f[1][x],f[2][x]})<<endl; return 0; }
B. 芦荀花
-
连通块数
即为所求。 -
部分分
-
连通块数等于边数减点数,考虑差的来源是由于连通块顶部的点导致的。稍微卡卡常,时间复杂度为
。点击查看代码
int fa[500010],dfn[500010],pos[500010],vis[500010],tot=0; pair<int,int>a[500010]; vector<int>e[500010]; void add(int u,int v) { e[u].push_back(v); } void dfs(int x,int father) { tot++; dfn[x]=tot; pos[tot]=x; fa[x]=father; for(int i=0;i<e[x].size();i++) { if(e[x][i]!=father) dfs(e[x][i],x); } } int main() { #define Isaac #ifdef Isaac freopen("fructus.in","r",stdin); freopen("fructus.out","w",stdout); #endif int n,m,b,ans=0,u,v,i,j,k; scanf("%d%d%d",&n,&m,&b); for(i=1;i<=n-1;i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(i=1;i<=n;i++) sort(e[i].begin(),e[i].end()); dfs(1,0); for(;m>=1;m--) { scanf("%d",&k); ans*=b; for(i=1;i<=k;i++) { scanf("%d%d",&a[i].first,&a[i].second); a[i].first^=ans; a[i].second^=ans; for(j=a[i].first;j<=a[i].second;j++) vis[pos[j]]=1; } ans=-1; for(i=k;i>=1;i--) { for(j=a[i].second;j>=a[i].first;j--) { vis[pos[j]]=0; ans+=(vis[fa[pos[j]]]==0); } } printf("%d\n",ans); } return 0; }
-
若连通块内部已经连通是容易处理的,取
判断即可。按照 序记录叶子节点后划分成若干条链后时间复杂度瓶颈不在判断某个点是否被选中,即使优化也没有什么大的用处,时间复杂度为 ,其中 为叶子个数。- 貌似把拆分成链转换成拆分成子树就可以通过
的测试点。
点击查看代码
int fa[500010],dfn[500010],vis[500010],tot=0; pair<int,int>a[500010]; vector<int>e[500010],leaf; void add(int u,int v) { e[u].push_back(v); } void dfs(int x,int father) { int flag=0; tot++; dfn[x]=tot; fa[tot]=dfn[father]; for(int i=0;i<e[x].size();i++) { if(e[x][i]!=father) { flag=1; dfs(e[x][i],x); } } if(flag==0) leaf.push_back(dfn[x]); } int main() { #define Isaac #ifdef Isaac freopen("fructus.in","r",stdin); freopen("fructus.out","w",stdout); #endif int n,m,b,ans=0,tmp,u,v,i,j,k; scanf("%d%d%d",&n,&m,&b); for(i=1;i<=n-1;i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(i=1;i<=n;i++) sort(e[i].begin(),e[i].end()); dfs(1,0); for(;m>=1;m--) { scanf("%d",&tmp); k=1; ans*=b; for(i=1;i<=tmp;i++) { scanf("%d%d",&a[i].first,&a[i].second); a[i].first^=ans; a[i].second^=ans; for(j=a[i].first;j<=a[i].second;j++) vis[j]=1; if(i>=2) { if(a[i].first==a[k].second+1) a[k].second=a[i].second; else { k++; a[k]=a[i]; } } } ans=-1; u=lower_bound(leaf.begin(),leaf.end(),a[k].first)-leaf.begin(); v=upper_bound(leaf.begin(),leaf.end(),a[k].second)-leaf.begin()-1; for(i=k;i>=1;i--) { while(leaf[u-1]>=a[i].first&&u-1>=0) u--; while(leaf[v]>a[i].second&&v>=0) v--; if(u>v) ans+=(vis[fa[a[i].first]]==0); else { for(j=u;j<=v;j++) { ans+=((vis[fa[(j==u)?a[i].first:(leaf[j-1]+1)]])==0); } if(a[i].second!=leaf[v]) ans+=(vis[fa[leaf[v]+1]]==0); } for(j=a[i].first;j<=a[i].second;j++) vis[j]=0; } printf("%d\n",ans); } return 0; }
- 貌似把拆分成链转换成拆分成子树就可以通过
-
-
正解
C. 豆蔻花
总结
读假题了,以为同时可以移动 个石子,最后的式子多一个连通块大小,直接假了。- 没想到
主席树维护二维数点的暴力做法。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18697627,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下