wzOI 202311.8-9 模拟赛题解
2023.11.9 competion
复盘
时间安排不太好,然后就是太纠结于一个想法了导致第二题不知道在想什么鬼东西,心态还是要放平啊。
A
明显大模拟,我想逃避一下,所以就skip了半个小时,发现后面三道一点思路都没有,然后就回来打 T1 大模拟。这个大模拟非常考验对工具的使用,幸好我造的数据比较多,而且搞过一些这种东西,就复制粘贴然后输入到代码里把变成程序语言,打了我一个半小时。打完的时候已经是两个小时过去了。
大致思路:复制信息到代码里,让代码将其加工成可以使用的代码语言,然后暴力乱搞即可。
B
我题目看错了(一开始看对了后来第二次回来看的时候看错了),以为必须选最前面连续的
正解
对于每个数,只有五种抉择:
- 不放
- 放进
- 乘
放进 - 放进
- 乘
放进
所以我们可以记一维表示
const int N=102,d=2662; int n,m,p[N],v[N]; ll f[2][N][5500],ans=-1e18; int main(){ n=read(),m=read(); for(int i=1;i<=n;i++) v[i]=read(),p[i]=read(); memset(f,-0x3f,sizeof(f)); f[0][0][d]=0; for(int i=1,o=1;i<=n;i++,o^=1) for(int k=0;k<=m;k++) for(int w=52;w<=2*d-52;w++) f[o][k][w]=max(f[o^1][k][w],max(max(f[o^1][k][w-2*p[i]],f[o^1][k][w+2*p[i]]),(k?max(f[o^1][k-1][w-4*p[i]],f[o^1][k-1][w+4*p[i]]):-(ll)1e18))+v[i]); for(int k=0;k<=m;k++) ans=max(ans,f[n&1][k][d]); printf("%lld\n",ans); return 0; }
C
T3 贪心没特判两个点都挂(为什么会有人在 5000 的点里面放一个 2 专门卡特判啊)。
正解就贪心,我一开始以为是什么神奇的数据结构。
我们肯定有一个上限(一个正排一个反排求差),我们每次交换如果都是交换最大的那最后结果也一定是最大的。
我们令
- 假设此时的
,那么交换后有 ,对答案的贡献为 。 - 如果
,那么有 ,对答案贡献为 。为无意义交换。
所以我们对每个
const int N=1e5+5; int n,k,a[N],b[N]; priority_queue<int>Q1; priority_queue<int,vector<int>,greater<int> >Q2; int main(){ for(int T=read();T--;){ n=read(),k=read(); ll ans=0; while(Q1.size())Q1.pop(); while(Q2.size())Q2.pop(); for(int i=1;i<=n;i++)a[i]=read(); for(int i=1;i<=n;i++){ b[i]=read(); ans+=abs(a[i]-b[i]); if(a[i]>b[i])Q1.push(b[i]),Q2.push(a[i]); else Q1.push(a[i]),Q2.push(b[i]); } if(n==2){ if(k&1)swap(a[1],a[2]); printf("%lld\n",1ll*abs(a[1]-b[1])+abs(a[2]-b[2])); continue; } while(Q1.size()&&Q1.top()>Q2.top()&&(k--)){ ans+=1ll*Q1.top()-Q2.top()<<1; Q1.pop(),Q2.pop(); } printf("%lld\n",ans); } return 0; }
D
题面打错了,导致我特殊性质看了好久看不出错,但是和样例不一样。最后以样例为准拿下暴力的
暴力思路就是每个时间跑一遍。
特殊分
正解就是线段树分治板子,不在这里讲了。
const int N=1e5+5; struct edge{ int u,v,l,r; }e[N<<1]; int n,m,T,fa[N<<1]; inline int find(int x){return (x==fa[x]?x:fa[x]=find(fa[x]));} namespace subtask_l{ inline bool cmp(const edge a,const edge b){return a.r>b.r;} int R; bool work(int L){ for(int i=0;i<=L-1;i++) puts("Yes"); sort(e+1,e+1+m,cmp); for(int t=R=e[1].r,i=1;t>=L;t--){ bool flag=1; while(i<=m&&e[i].r==t){ if(find(e[i].u)==find(e[i].v)){flag=0;break;} fa[find(e[i].u+n)]=find(e[i].v); fa[find(e[i].v+n)]=find(e[i].u); i++; } if(!flag){R=t-1;break;} if(t==L)R=L-1; } for(int i=L;i<=R;i++)puts("No"); for(int i=R+1;i<T;i++)puts("Yes"); return 0; } } namespace subtask_r{ inline bool cmp(const edge a,const edge b){return a.l<b.l;} int L; bool work(int R){ sort(e+1,e+1+m,cmp); for(int t=L=e[1].l,i=1;t<R;t++){ bool flag=1; while(i<=m&&e[i].l==t){ if(find(e[i].u)==find(e[i].v)){flag=0;break;} fa[find(e[i].u+n)]=find(e[i].v); fa[find(e[i].v+n)]=find(e[i].u); i++; } if(!flag){L=t-1;break;} if(t==R-1)L=R-1; } for(int i=0;i<=L;i++)puts("Yes"); for(int i=L+1;i<R;i++)puts("No"); for(int i=R;i<T;i++)puts("Yes"); return 0; } } namespace subtask_v{ int c[N],t; vector<edge>f[N]; bool dfs(int x){ for(edge PI:f[x])if(PI.l<=t&&t<PI.r){ int y=PI.v; if(!c[y]){ c[y]=-c[x]; if(!dfs(y))return 0; } else if(c[y]==c[x])return 0; } return 1; } bool work(){ for(int i=1;i<=m;i++){ f[e[i].u].push_back(e[i]); f[e[i].v].push_back({e[i].v,e[i].u,e[i].l,e[i].r}); } for(t=0;t<T;t++){ for(int i=1;i<=n;i++)c[i]=0; bool flag=1; for(int i=1;i<=n;i++) if(!c[i])c[i]=1,flag&=dfs(i); puts(flag?"Yes":"No"); } return 0; } } int samL,samR; int main(){ n=read(),m=read(),T=read(); for(int i=1;i<=(n<<1);i++)fa[i]=i; for(int i=1;i<=m;i++){ int u=read(),v=read(),l=read(),r=read(); if(i>1&&l!=samL)samL=0; else if(i==1)samL=l; if(i>1&&r!=samR)samR=0; else if(i==1)samR=r; e[i]={u,v,l,r}; } if(samL)return subtask_l::work(samL),0; else if(samR)return subtask_r::work(samR),0; subtask_v::work(); return 0; }
2023.11.8 competition
前言
因为这场我就写了两题就不单独发一个了。
A
显然可以状压然后直接暴力,不过需要一点点贪心优化吧,半个小时打完。
代码很丑。
int n,m,a[100005],s[25],ans; void dfs(int res){ bool flag=0; for(int i=2;i<(1<<m)-1;i++){ if(!s[i])continue; for(int j=1;j<i;j++){ if(!s[j])continue; if(i+j!=(i|j))continue; int minn=min(s[i],s[j]); s[i]-=minn; s[j]-=minn; s[i|j]+=minn; flag=1; dfs(res-minn); s[i|j]-=minn; s[i]+=minn; s[j]+=minn; } } if(!flag)ans=min(ans,res); } int main(){ n=read(),m=read(); for(int i=0;i<m;i++){ int k=read(); for(int j=1;j<=k;j++){ int w=read(); a[w]|=(1<<i); } } for(int i=1;i<=n;i++)s[a[i]]++; int res=n-s[0];s[0]=0; for(int i=(1<<m)-2;~i;--i){ if(s[i]&&s[((1<<m)-1)^i]){ int minn=min(s[i],s[((1<<m)-1)^i]); s[i]-=minn; s[((1<<m)-1)^i]-=minn; s[(1<<m)-1]+=minn; res-=minn; } } for(int i=0;i<m;i++){ for(int j=3;s[1<<i]&&j<(1<<m)-1;j++){ if(__builtin_popcount(j)==1)continue; if((1<<i)+j!=((1<<i)|j))continue; if(!s[j])continue; int minn=min(s[1<<i],s[j]); s[1<<i]-=minn; s[j]-=minn; s[(1<<i)|j]+=minn; res-=minn; } } ans=res; dfs(res); cout<<ans; return 0; }
B
树形dp。
至多有一个不好求,先想想怎么让他就不超过,即在同一层选不超过k个子树吧,这个只需要跑个优先队列什么的找最大贡献,如果还要被选需要少选一个,到k的话可以直接记入答案之类的。
那有一个呢?
我们发现
其实自己是不需要记的,因为用不到这一维。
令
为什么这里取
为什么不用换根呢?因为父亲子树如果选了自己的话就已经算了包括自己的答案了,如果没加说明自己不够优,总之所有情况都被考虑到了。
看不懂的话可以看代码。
int n,m; ll f[2][N],ans; vector<PII>F[N]; void dfs(int x,int fa){ ll my=0; int id=0; priority_queue<ll>Q; for(PII PI:F[x]){ int y=PI.first,w=PI.second; if(y==fa)continue; dfs(y,x); my+=f[0][y]+w; Q.push(f[0][y]+w); if(f[1][y]+w>f[1][x])f[1][x]=f[1][y]+w,id=y; } if(Q.size()<m)f[0][x]=my,my=0; else{ for(int T=m-1;T--;)f[0][x]+=Q.top(),Q.pop(); ans=max(ans,f[0][x]+Q.top()); } while(!Q.empty())Q.pop(); for(PII PI:F[x]){ int y=PI.first,w=PI.second; if(y==fa)continue; if(y!=id)Q.push(f[0][y]+w); } if(Q.size()<m-1) while(!Q.empty())f[1][x]+=Q.top(),Q.pop(); else{ for(int T=m-2;T--;)f[1][x]+=Q.top(),Q.pop(); ans=max(ans,f[1][x]+Q.top()); } while(!Q.empty())Q.pop(); f[1][x]=max(f[1][x],my); ans=max(ans,f[1][x]); ans=max(ans,f[0][x]); return; } int main(){ n=read(),m=read(); if(!m)return puts("0"),0; for(int i=1;i<n;i++){ int u=read(),v=read(),w=read(); F[u].push_back({v,w}),F[v].push_back({u,w}); } if(m==1){ for(int x=1;x<=n;x++){ ll res=0; for(PII PI:F[x])res+=PI.second; if(res>ans)ans=res; } printf("%lld",ans); return 0; } dfs(1,0); cout<<ans; return 0; }
本文作者:NBest
本文链接:https://www.cnblogs.com/NBest/p/17822932.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现