news 2026/4/16 3:33:20

2025-12-11 hetao1733837的刷题笔记

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
2025-12-11 hetao1733837的刷题笔记

2025-12-11 hetao1733837的刷题笔记

LG5787 【模板】线段树分治 / 二分图

原题链接:【模板】线段树分治 / 二分图

分析

我好像有点理解了……

13点39分

卧槽,豁然开朗!这玩意就是说利用线段树,把一段区间扔进整棵树,然后线段树每个点用v e c t o r vectorvector记录这段时间消失的节点,在分治的时候,取出对应时间段的线段树,然后判断是不是二分图就行了(并查集)。
行,继续理解撤销。
那似乎很容易想了。哎,我的二分图并不熟练。

正解

#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=200005;intn,m,k;intfa[N<<1],sz[N<<1];structnode{intp,v;node(intpos,intval){p=pos;v=val;}};stack<node>father,size;vector<int>tr[N<<2];vector<bool>res;intfind(intx){returnx==fa[x]?x:find(fa[x]);}voidmerge(intx,inty){intfx=find(x),fy=find(y);if(fx==fy)return;if(sz[fx]<sz[fy])swap(fx,fy);size.push(node(fy,sz[fy]));sz[fx]+=sz[fy];father.push(node{fy,fa[fy]});fa[fy]=fx;}voidwork(){fa[father.top().p]=father.top().v;father.pop();sz[size.top().p]=size.top().v;size.pop();}voidmodify(intp,intl,intr,ints,intt,intval){if(s<=l&&r<=t){tr[p].push_back(val);return;}intmid=(l+r)>>1;if(s<=mid)modify(p<<1,l,mid,s,t,val);if(t>mid)modify(p<<1|1,mid+1,r,s,t,val);}structedge{intu,v;}e[N];voidsolve(intp,intl,intr){autolvl=father.size();boolflag=1;for(autotmp:tr[p]){intfu=find(e[tmp].u),fv=find(e[tmp].v);if(fu==fv){for(inti=l;i<=r;i++)res.push_back(false);flag=false;break;}merge(e[tmp].u,e[tmp].v+n);merge(e[tmp].v,e[tmp].u+n);}if(flag){if(l==r){res.push_back(true);}else{intmid=(l+r)>>1;solve(p<<1,l,mid);solve(p<<1|1,mid+1,r);}}while(father.size()>lvl){work();}}signedmain(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n>>m>>k;for(inti=1;i<=(n<<1);i++){fa[i]=i;sz[i]=1;}for(inti=1;i<=m;i++){intx,y,l,r;cin>>e[i].u>>e[i].v>>l>>r;modify(1,1,k,l+1,r,i);}solve(1,1,k);for(autov:res){if(v)cout<<"Yes"<<'\n';elsecout<<"No"<<'\n';}}

LG4219 [BJOI2014] 大融合

原题链接:[BJOI2014] 大融合

分析

首先应该明确的是,如何求取树上经过某一条边的路径数量,比较显然的就是,呃,还是有个图好一点,我找一个。

好的,对于节点1 11和节点2 22之间那一条边,其左部有2 , 4 , 5 , 8 , 9 , 10 2,4,5,8,9,102,4,5,8,9,106 66个点,其右部有1 , 3 , 6 , 7 1,3,6,71,3,6,74 44个点,则经过该边的路径数量共6 × 4 = 24 6\times 4=246×4=24条。
从这个角度出发,我要多维护每个连通块内部每个点的子树大小。
同样对于时间去处理?
那我会有种离线思路。
我直接建出最终的树,然后对于一条边的加入,令其在初始时间到加入时间这段时间不可用,就变成了模板,但我好像不太会动态维护子树大小,细想起来其实也不难吧……
好像给的思路差不多,行,我搓一下代码。
比模板多的恐怕也只有各种map了,其实可以统一存进一个s t r u c t structstruct里,显得优雅一些?

正解

#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=100005;charop;intn,q,fa[N],sz[N];structnode{intpos,val;node(intp,intv){pos=p;val=v;}};stack<node>siz,father;intfind(intx){returnx==fa[x]?x:find(fa[x]);}voidmerge(intx,inty){x=find(x);y=find(y);if(x==y)return;if(sz[x]<sz[y])swap(x,y);siz.push(node(x,sz[x]));sz[x]+=sz[y];father.push(node(y,fa[y]));fa[y]=x;}voidwork(){fa[father.top().pos]=father.top().val;father.pop();sz[siz.top().pos]=siz.top().val;siz.pop();}vector<pair<int,int>>tr[N<<4];voidmodify(intp,intl,intr,ints,intt,pair<int,int>v){if(s<=l&&r<=t){tr[p].push_back(v);return;}intmid=(l+r)>>1;if(s<=mid)modify(p<<1,l,mid,s,t,v);if(t>mid)modify(p<<1|1,mid+1,r,s,t,v);}inttim;map<pair<int,int>,int>tims;structopt{intl,r;pair<int,int>v;}opp[N<<3];intncnt;map<int,int>ask;map<int,pair<int,int>>asklr;intans[N<<3];voidsolve(intp,intl,intr){intlvl=father.size();for(autou:tr[p]){merge(u.first,u.second);}if(l==r){if(ask[l]){intx=asklr[l].first,y=asklr[l].second;ans[l]=sz[find(x)]*sz[find(y)];}}else{intmid=(l+r)>>1;solve(p<<1,l,mid);solve(p<<1|1,mid+1,r);}while(father.size()>lvl){work();}}signedmain(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n>>q;for(inti=1;i<=n;i++){fa[i]=i;sz[i]=1;}for(intcs=1;cs<=q;cs++){cin>>op;intx,y;cin>>x>>y;if(op=='A'){tims[{x,y}]=++tim;}else{pair<int,int>tmp={x,y};opp[++ncnt]={tims[tmp],++tim,tmp};ask[++tim]=1;asklr[tim]=tmp;tims[tmp]=++tim;}}inttmp=++tim;for(autoi:tims){opp[++ncnt]={tims[i.first],tmp,i.first};}for(inti=1;i<=ncnt;i++){modify(1,1,tim,opp[i].l,opp[i].r,opp[i].v);}solve(1,1,tim);for(inti=1;i<=tim;i++){if(ask[i]){cout<<ans[i]<<'\n';}}}

LG2056 [ZJOI2007] 捉迷藏

原题链接:[ZJOI2007] 捉迷藏

分析

这不是我昨天被h a c k hackhack的点分树题吗?今天又碰到了,这是让我和他死磕到底吗?大课间之前最好能吃出来!
坏了,代码里有b i t s e t bitsetbitset,我还没学!
那咋办?现学!
并不很难吧,难道我可以做LG11831 [省选联考 2025] 追忆了?假的,黑题要是随便做,场上碰见的都成不可做题了。
从点分治的角度去想,距离最长的点显然最好分别在两棵子树内。
改变颜色似乎是在一段时间不可选(亮了),一段时间可选(不亮),那就成了板子?
真假的?找题解求证一下。

错误总结

错误点在于两点最长距离的计算方式,正确的方式是找到树上黑点作为端点构成的直径,然后对于每次新加入黑点点集后的直径,只可能维持不变、一个端点不变另一个端点变成新加入的黑点。
感觉被骗了,ber,阴成啥了?这个所谓直径的说法不过是我说法的形式化?感觉我理解地还算对。
但是,树上最长链问题就要往直径上想!,详情参考L G 8173 [ C E O I 2021 ] N e w s p a p e r s LG8173 [CEOI 2021] NewspapersLG8173[CEOI2021]Newspapers

正解

#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=500005,M=500005;intn,q;charop;structnode{intpos,val;node(intp,intv){pos=p;val=v;}};vector<int>e[N];intsz[N],de[N],fa[N],top[N],son[N];//树剖求 LCAvoiddfs1(intu,intpa){de[u]=de[pa]+1;fa[u]=pa;sz[u]=1;for(autov:e[u]){if(v==pa)continue;dfs1(v,u);sz[u]+=sz[v];if(sz[v]>sz[son[u]])son[u]=v;}}voiddfs2(intu,inttp){top[u]=tp;if(son[u]){dfs2(son[u],tp);}for(autov:e[u]){if(v==fa[u]||v==son[u])continue;dfs2(v,v);}}intLCA(intx,inty){while(top[x]!=top[y]){if(de[top[x]]<de[top[y]])swap(x,y);x=fa[top[x]];}if(de[x]<de[y])returnx;returny;}intdist(intx,inty){returnde[x]+de[y]-de[LCA(x,y)]*2;}vector<int>tr[N<<2];voidmodify(intp,intl,intr,ints,intt,intval){if(s<=l&&r<=t){tr[p].push_back(val);return;}intmid=(l+r)>>1;if(s<=mid)modify(p<<1,l,mid,s,t,val);if(t>mid)modify(p<<1|1,mid+1,r,s,t,val);}stack<pair<int,int>>stk;intu,v,ans[N];voidsolve(intp,intl,intr){autolvl=stk.size();for(autox:tr[p]){stk.push({u,v});if(!u&&!v){u=x;v=x;}else{vector<int>vct={dist(u,v),dist(u,x),dist(x,v)};sort(vct.begin(),vct.end(),greater<int>());if(vct[0]==dist(u,x))v=x;elseif(vct[0]==dist(x,v))u=x;}}if(l==r){if(!u||!v)ans[l]=-1;elseans[l]=dist(u,v);}else{intmid=(l+r)>>1;solve(p<<1,l,mid);solve(p<<1|1,mid+1,r);}while(stk.size()!=lvl){autotop=stk.top();u=top.first;v=top.second;stk.pop();}}intlst[N];bitset<N>col;bitset<M>ha;signedmain(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n;for(inti=1;i<n;i++){intu,v;cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}dfs1(1,0);dfs2(1,1);for(inti=1;i<=n;i++){lst[i]=1;}cin>>q;for(inti=2;i<=q+1;i++){cin>>op;if(op=='C'){intx;cin>>x;if(!col[x]){col[x]=1;modify(1,1,q+2,lst[x],i,x);}else{col[x]=0;lst[x]=i;}}else{ha[i]=1;}}for(inti=1;i<=n;i++){if(!col[i]){modify(1,1,q+2,lst[i],q+2,i);}}solve(1,1,q+2);for(inti=1;i<=q+2;i++){if(ha[i])cout<<ans[i]<<'\n';}}

LG4556 【模板】线段树合并 / [Vani有约会] 雨天的尾巴

原题链接:【模板】线段树合并 / [Vani有约会] 雨天的尾巴

分析

啊?难道开值域棵线段树?有点恐怖了!
假的,线段树合并即可。思想我显然理解了,但是吧,pyd上课不变代码写全是何意味?发现还得套 LCA?

正解

#include<bits/stdc++.h>usingnamespacestd;constintN=100005;constintV=100001;intn,m,f[N][22],de[N],ans[N];vector<int>e[N];structnode{intid,cnt;friendbooloperator<(node tmp1,node tmp2){if(tmp1.cnt==tmp2.cnt){returntmp1.id>tmp2.id;}returntmp1.cnt<tmp2.cnt;}friendnodeoperator+(node tmp1,node tmp2){return(node){tmp1.id,tmp1.cnt+tmp2.cnt};}};vector<node>tag[N];structsegtree{node tr[N*40];intls[N*40],rs[N*40];intncnt;voidinit(){ncnt=n;for(inti=1;i<=n;i++){tr[i]={0,0};ls[i]=rs[i]=0;}}voidpushup(intp){tr[p]=max(tr[ls[p]],tr[rs[p]]);}voidmodify(intp,intl,intr,node val){if(r-l==1){tr[p]=val+tr[p];return;}intmid=(l+r)>>1;if(val.id<mid){if(!ls[p]){ls[p]=++ncnt;tr[ls[p]]={0,0};}modify(ls[p],l,mid,val);}else{if(!rs[p]){rs[p]=++ncnt;tr[rs[p]]={0,0};}modify(rs[p],mid,r,val);}pushup(p);}voidmerge(intx,inty,intl,intr){if(!x||!y)return;if(r-l==1){tr[x]=tr[x]+tr[y];return;}intmid=(l+r)>>1;if(ls[x]&&ls[y]){merge(ls[x],ls[y],l,mid);}elseif(ls[y]){ls[x]=ls[y];}if(rs[x]&&rs[y]){merge(rs[x],rs[y],mid,r);}elseif(rs[y]){rs[x]=rs[y];}pushup(x);}}T;voidinit(){for(inti=1;i<=20;i++)for(intu=1;u<=n;u++)f[u][i]=f[f[u][i-1]][i-1];}voiddfs(intu){for(autov:e[u]){if(v!=f[u][0]){f[v][0]=u;de[v]=de[u]+1;dfs(v);}}}intlca(intx,inty){if(de[x]<de[y]){swap(x,y);}intk=de[x]-de[y];for(inti=0;i<=20;i++){if(k&(1<<i))x=f[x][i];}if(x==y)returny;for(inti=20;i>=0;i--)if(f[x][i]!=f[y][i]){x=f[x][i];y=f[y][i];}returnf[x][0];}voidMerge(intu){for(autov:e[u]){if(v!=f[u][0]){Merge(v);T.merge(u,v,0,V);}}for(autok:tag[u]){T.modify(u,0,V,k);}ans[u]=T.tr[u].id;}intmain(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n>>m;T.init();for(inti=1;i<n;i++){inta,b;cin>>a>>b;e[a].push_back(b);e[b].push_back(a);}dfs(1);init();for(inti=1;i<=m;i++){intx,y,z;cin>>x>>y>>z;intLCA=lca(x,y);tag[x].push_back((node){z,1});tag[y].push_back((node){z,1});tag[LCA].push_back((node){z,-1});if(f[LCA][0]>0)tag[f[LCA][0]].push_back((node){z,-1});}Merge(1);for(inti=1;i<=n;i++){cout<<ans[i]<<'\n';}return0;}

何意味?凭啥?我左移 5 位开 32 倍凭啥卡我?开40倍你过了?

LG6773 [NOI2020] 命运

原题链接:[NOI2020] 命运

分析

19点28分

不行,我先写到蓝,这样洛谷上蓝题数量就和黄题一样了,嘻嘻。

20点37分

哦,终于把下面那道题过了。
回家打 CF!这题太……难以评价……

正解

LG2279 [HNOI2003] 消防局的设立

原题链接:[HNOI2003] 消防局的设立

分析

自己打了一发,过了小样例,交上去 10pts,哭晕在厕所/(ㄒoㄒ)/~~
显然我是从 ZR 题单的树形D P DPDP里把这题扒出来的,所以直接树形D P DPDP,设f u , 0 / 1 / 2 f_{u,0/1/2}fu,0/1/2表示u uu节点,其子树内最近的消防站距离他0 / 1 / 2 0/1/20/1/2的建造消防站个数。

错误分析

我们只考虑了u uu的子树,但是,u uu为什么不能从其祖先转移而来?
那么,多设两种状态,即设f u , 0 / 1 / 2 / 3 / 4 f_{u,0/1/2/3/4}fu,0/1/2/3/4表示从节点u uu向上覆盖2 / 1 / 0 / − 1 / − 2 2/1/0/-1/-22/1/0/1/2层的最小消防站个数。
转移显然,
f u , 0 = 1 + ∑ v ∈ s o n [ u ] f v , 4 f_{u, 0}=1+\sum\limits_{v\in son[u]}f_{v, 4}fu,0=1+vson[u]fv,4
f u , 1 = min ⁡ v ∈ s o n [ u ] ( f v , 0 + ∑ t ∈ s o n [ u ] , t ≠ v f t , 3 , f u , 0 ) f_{u, 1}=\min\limits_{v\in son[u]}(f_{v,0}+\sum\limits_{t\in son[u],t\neq v}f_{t,3}, f_{u,0})fu,1=vson[u]min(fv,0+tson[u],t=vft,3,fu,0)
f u , 2 = min ⁡ v ∈ s o n [ u ] ( f v , 1 + ∑ t ∈ s o n [ u ] , t ≠ v f t , 2 , f u , 0 , f u , 1 ) f_{u, 2}=\min\limits_{v\in son[u]}(f_{v,1}+\sum\limits_{t\in son[u],t\neq v}f_{t,2}, f_{u,0},f_{u,1})fu,2=vson[u]min(fv,1+tson[u],t=vft,2,fu,0,fu,1)
f u , 3 = min ⁡ ( ∑ v ∈ s o n [ u ] f v , 2 , f u , 0 , f u , 1 , f u , 2 ) f_{u,3}=\min(\sum\limits_{v\in son[u]}f_{v,2},f_{u, 0},f_{u, 1},f_{u, 2})fu,3=min(vson[u]fv,2,fu,0,fu,1,fu,2)
f u , 4 = min ⁡ ( ∑ v ∈ s o n [ u ] f v , 3 , f u , 0 , f u , 1 , f u , 2 , f u , 3 ) f_{u,4}=\min(\sum\limits_{v\in son[u]}f_{v,3},f_{u, 0},f_{u, 1},f_{u, 2},f_{u, 3})fu,4=min(vson[u]fv,3,fu,0,fu,1,fu,2,fu,3)

正解

直接建有向,少记录一个f a fafa

#include<bits/stdc++.h>usingnamespacestd;constintN=1005;intn;vector<int>e[N];intf[N][5];voiddfs(intu){f[u][0]=1;f[u][3]=0;f[u][4]=0;for(autov:e[u]){dfs(v);f[u][0]+=f[v][4];f[u][3]+=f[v][2];f[u][4]+=f[v][3];}if(e[u].size()==0){f[u][1]=f[u][2]=1;}else{f[u][1]=f[u][2]=0x3f3f3f3f;for(autov:e[u]){intf1=f[v][0],f2=f[v][1];for(autot:e[u]){if(v==t)continue;f1+=f[t][3];f2+=f[t][2];}f[u][1]=min(f[u][1],f1);f[u][2]=min(f[u][2],f2);}}for(inti=1;i<=4;i++){f[u][i]=min(f[u][i],f[u][i-1]);}}intmain(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n;for(inti=2;i<=n;i++){inta;cin>>a;e[a].push_back(i);}dfs(1);cout<<f[1][2];}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 7:21:45

Gitee崛起:中国开发者生态的“数字底座“正在重构

Gitee崛起&#xff1a;中国开发者生态的"数字底座"正在重构 在中国数字经济高速发展的背景下&#xff0c;本土代码托管平台Gitee正以独特的价值定位和技术优势&#xff0c;重塑着国内软件开发的基础设施格局。作为中国开发者生态的重要基础设施&#xff0c;Gitee不仅…

作者头像 李华
网站建设 2026/4/16 7:21:45

【推荐系统】深度学习训练框架(十六):模型并行——推荐系统的TorchRec和大语言模型的FSDP(Fully Sharded Data Parallel)

&#x1f4e6; 第一部分&#xff1a;TorchRec 实战教程 TorchRec是PyTorch的领域库&#xff0c;专为大规模推荐系统设计。其核心是解决超大规模嵌入表在多GPU/多节点上的高效训练问题。 1. 安装与环境配置 首先安装TorchRec及其依赖。推荐使用CUDA环境以获得最佳性能。 # 1.…

作者头像 李华
网站建设 2026/4/16 7:20:52

Dify Custom Tool 调用超时问题排查与解决方案(claude-4.5-opus-high)

在使用 Dify 的 Custom Tool&#xff08;自定义工具&#xff09;功能调用外部 API 时&#xff0c;你是否遇到过这样的问题&#xff1a; 工具调用反复重试&#xff0c;日志中出现多次相同请求API 明明执行成功了&#xff0c;但 Dify 显示超时失败复杂的 AI 处理流程总是在中途断…

作者头像 李华
网站建设 2026/4/16 7:21:49

day123—二分查找—H 指数 II(LeetCode-275)

题目描述 给你一个整数数组 citations &#xff0c;其中 citations[i] 表示研究者的第 i 篇论文被引用的次数&#xff0c;citations 已经按照 非降序排列 。计算并返回该研究者的 h 指数。 h 指数的定义&#xff1a;h 代表“高引用次数”&#xff08;high citations&#xff…

作者头像 李华
网站建设 2026/4/16 7:22:13

从零搭建VSCode量子作业监控面板:3小时快速上手教程,错过等于落伍

第一章&#xff1a;VSCode 的量子作业监控面板在现代量子计算开发中&#xff0c;可视化与实时监控是提升调试效率的关键。VSCode 通过扩展插件架构&#xff0c;支持集成定制化的量子作业监控面板&#xff0c;使开发者能够在编码环境中直接观察量子电路执行状态、资源分配及任务…

作者头像 李华
网站建设 2026/4/16 7:20:45

【收藏必备】2023年大模型转型完全指南:从零入门到就业的全方位攻略

这篇文章提供了大模型领域从零到就业的全面转型攻略&#xff0c;包括明确职业方向、掌握基础知识、深入学习大模型技术、参与实践项目、加入开源社区、利用学习资源以及职业发展建议等内容。文章不仅提供了技术学习路径&#xff0c;还包含了职业规划和持续学习的方法&#xff0…

作者头像 李华