暑假集训CSP提高模拟13
1.高一上六月下旬日记2.【MX-S1】梦熊周赛 · 提高组 1(同步赛)3.牛客周赛 Round 494.高一上七月上旬日记5.Denso Create Programming Contest 2024(AtCoder Beginner Contest 361)6.NOIP2024模拟17.NOIP2024模拟28.高一上七月中旬日记9.NOIP2024模拟310.CSP提高组模拟111.暑假集训CSP提高模拟112.暑假集训CSP提高模拟213.暑假集训CSP提高模拟314.暑假集训CSP提高模拟415.高一上七月下旬日记16.暑假集训 加赛117.暑假集训CSP提高模拟518.暑假集训CSP提高模拟619.加赛220.暑假集训CSP提高模拟721.暑假集训CSP提高模拟822.暑假集训CSP提高模拟923.暑假集训CSP提高模拟1024.暑假集训CSP提高模拟1125.暑假集训CSP提高模拟1226.高一上八月上旬日记
27.暑假集训CSP提高模拟13
28.欢欢乐乐赛赛29.暑假集训CSP提高模拟1430.暑假集训CSP提高模拟1531.暑假集训CSP提高模拟1632.暑假集训CSP提高模拟1733.高一上八月中旬日记34.暑假集训CSP提高模拟1835.暑假集训CSP提高模拟1936.暑假集训CSP提高模拟2037.暑假集训CSP提高模拟2138.暑假集训CSP提高模拟2239.【LGR-196-Div.4】洛谷入门赛 #2640.暑假集训CSP提高模拟2341.牛客周赛 Round 5642.暑假集训CSP提高模拟2443.暑假集训CSP提高模拟 2544.高一上八月下旬日记45.暑假集训CSP提高模拟2646.暑假集训CSP提高模拟2747.牛客小白月赛99暑假集训CSP提高模拟13
暑假集训CSP提高模拟13
P185. 小孩召开法 1
-
部分分
- 未知
:乱搞。
- 未知
-
正解
- 状压加记忆化搜索。
- 记录所选字符串的状态及上一个选择的字符串。当存在对方必败时自己必胜。
点击查看代码
int f[1<<18][18]; string s[20]; bool dfs(int x,int last,int n) { if(f[x][last]==-1) { f[x][last]=0; for(int i=0;i<=n-1;i++) { if(((x>>i)&1)==0) { if(last==0||s[last][s[last].size()-1]==s[i+1][0]) { if(dfs(x|(1<<i),i+1,n)==0) { f[x][last]=1; break; } } } } } return f[x][last]; } int main() { int n,i; cin>>n; for(i=1;i<=n;i++) { cin>>s[i]; } memset(f,-1,sizeof(f)); if(dfs(0,0,n)==1) { cout<<"First"<<endl; } else { cout<<"Second"<<endl; } return 0; }
P188. 小孩召开法 2
-
部分分
:乱搞。
-
正解
- 由数据范围,猜测询问次数介于
之间。 次询问处理出每个点的深度,然后从小到大枚举深度进行处理。- 接下来对
的询问,由 ,我们就可以得到 的深度。 - 设当前已经建出了深度为
层的二叉树,未知点为 ,已知点为 。询问得到 的深度后,我们就可以知道 是哪个节点。由于是二叉树, 一定位于 的两棵子树内,那么 的父亲节点一定位于 除 所在子树内的另一棵子树。 - 令
初始为根节点, 为 所在的重链的末端点,此时 一定在 所在的重链上,从 开始往下跳重儿子直至 ,然后走到轻子树,接着令 是这棵轻子树的根节点,重复上述过程直至 。 - 连上边后再往上跳更新轻重儿子。
- 最后的询问次数为
,因为常数很小所以可以通过。
点击查看代码
int fa[3010],dep[3010],son[3010],siz[3010],bot[3010]; vector<int>pos[3010],e[3010]; void dfs(int x) { siz[x]=1; son[x]=0; bot[x]=x; for(int i=0;i<e[x].size();i++) { dfs(e[x][i]); siz[x]+=siz[e[x][i]]; son[x]=(siz[e[x][i]]>siz[son[x]])?e[x][i]:son[x]; bot[x]=bot[son[x]]; } } void solve(int x) { int y=1,d; while(dep[y]!=dep[x]-1) { cout<<"? "<<x<<" "<<bot[y]<<endl; cin>>d; d=(dep[x]+dep[bot[y]]-d)/2; while(dep[y]<d) { y=son[y];//跳重儿子 } if(dep[y]!=dep[x]-1) { y=e[y][0]^e[y][1]^son[y];//取轻儿子 //因为一定有轻儿子,所以不用担心会 RE } } fa[x]=y; e[y].push_back(x); } int main() { int n,i,j; cin>>n; for(i=2;i<=n;i++) { cout<<"? "<<1<<" "<<i<<endl; cin>>dep[i]; pos[dep[i]].push_back(i); } for(i=1;i<=n;i++) { dfs(1); for(j=0;j<pos[i].size();j++) { solve(pos[i][j]); } } cout<<"! "; for(i=2;i<=n;i++) { cout<<fa[i]<<" "; } cout<<endl; return 0; }
- 由数据范围,猜测询问次数介于
T176. 小孩召开法 3
-
部分分
:每组询问跑一遍 背包。
-
正解
- 将询问离线下来,然后进行分治。
- 考虑猫树分治,只单独处理跨过中点的询问,其他询问下放至左右递归中。特判叶子节点的处理。
- 因过程和猫树很像,所以被称作猫树分治。
- 对于跨过中点的询问,暴力进行背包合并即可。
点击查看代码
struct node { ll l,t,id; }; ll h[40010],w[40010],ans[200010],f[40010][210]; vector<node>q[40010]; void solve(ll l,ll r) { if(l==r) { for(ll i=0;i<q[r].size();i++) { if(q[r][i].l==l) { ans[q[r][i].id]=(q[r][i].t>=h[l])*w[l]; } } return; } ll mid=(l+r)/2; memset(f[mid],0,sizeof(f[mid]));//注意清空 f[mid][h[mid]]=w[mid]; for(ll i=mid-1;i>=l;i--) { for(ll j=1;j<=200;j++) { f[i][j]=f[i+1][j]; if(j-h[i]>=0) { f[i][j]=max(f[i][j],f[i+1][j-h[i]]+w[i]); } } } memset(f[mid+1],0,sizeof(f[mid+1]));//注意清空 f[mid+1][h[mid+1]]=w[mid+1]; for(ll i=mid+2;i<=r;i++) { for(ll j=1;j<=200;j++) { f[i][j]=f[i-1][j]; if(j-h[i]>=0) { f[i][j]=max(f[i][j],f[i-1][j-h[i]]+w[i]); } } } for(ll i=l;i<=r;i++) { for(ll j=1;j<=200;j++) { f[i][j]=max(f[i][j],f[i][j-1]); } } for(ll i=mid+1;i<=r;i++) { for(ll j=0;j<q[i].size();j++) { if(l<=q[i][j].l&&q[i][j].l<=mid) { for(ll k=0;k<=q[i][j].t;k++) { ans[q[i][j].id]=max(ans[q[i][j].id],f[i][k]+f[q[i][j].l][q[i][j].t-k]); } } } } solve(l,mid); solve(mid+1,r); } int main() { ll n,m,l,r,t,i; cin>>n>>m; for(i=1;i<=n;i++) { cin>>h[i]; } for(i=1;i<=n;i++) { cin>>w[i]; } for(i=1;i<=m;i++) { cin>>l>>r>>t; q[r].push_back((node){l,t,i}); } solve(1,n); for(i=1;i<=m;i++) { cout<<ans[i]<<endl; } return 0; }
T177. 小孩召开法 4
- 原题: [AGC056B] Range Argmax
- 部分分
:输出样例 。
- 正解
- 过于抽象,直接贺官方题解了。
同一个
可能对应多个 ,因此这样计数比较困难。考虑反过来计数。
对于给定的
,我们将按照以下的方式构造 :- 令
。 - 我们从
开始依次递减地考虑每个值 。对于每个值,我们找到 能放的最左侧的位置,放进去。
计数可以通过这种方式生成的
。设当前最值为
。我们首先确定下标 ,使得 。对于所有包含 的区间 ,有 。删除这些包含 的区间后,我们可以分别考虑位于 左右两侧的区间。由于 为最左侧的可以放 的位置,右侧的数均小于左侧的数,这部分是和原问题等价但规模更小的子问题。现在考虑左侧。我们令
为 左侧最大元素对应的下标。有:必定存在一个左侧区间同时包含 和 。考虑反证。如果左侧没有区间同时包含
和 ,那我们可以令 ,这必定是更优且满足要求的。这与假设矛盾,因此必定存在同时包含 和 的左侧区间。
因此,左侧区间所填的数的最大值必定大于等于 。考虑区间 dp。我们设
为 区间满足最大值的下标大于等于 的方案数。可以通过枚举中点以及预处理区间最大值的方式转移。转移时加入后缀和即可快速得到最终答案。时间复杂度
。
总结
赛时没读懂题。
后记
-
比赛头图。
-
题目背景均来自或改编自 LibreOJ 6731. 「2019 山东一轮集训 Day3」小孩召开法 。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18336722,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】