2024.8.6 模拟赛 14
模拟赛
蜀道之难,难于上青天。
打过一版忘保存了。
蜀道难
T1
唐题挂分,一张饼同一时刻只能在一个锅上,所以显然时间一定不会低于最大的饼。
假如每一时刻都能将锅占满,那么时间就是 \(\lceil \frac{\sum a}{m} \rceil\) ,取 \(max\) 就好了。
好像能用二维覆盖解释。
code
#include<bits/stdc++.h>
using namespace std;
#define LL long long
int n,m;
LL ans,mx;
int main()
{
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
LL x; scanf("%lld",&x);
ans+=x;
mx=max(mx,x);
}
ans=(LL)ceil(ans*1.0/m);;
printf("%lld\n",max(mx,ans));
return 0;
}
T2 大富翁
下次一定记得保存。
题解讲的都很模糊,其实差值法想想还挺清晰的。。。
容易发现最终的收益与选点的顺序无关,只与最终状态有关。
我们单独考虑每一个点的贡献,因为一个点不是被小 \(A\) 选就是被小 \(B\) 选,如果小 \(B\) 选的话小 \(A\) 的收益就是 \(-{收益}_B\),
所以小 \(A\) 选实际的净收益就是 \({收益}_A+{收益}_B\)。
设当前要选的点为 \(x\),\(x\) 的子树中属于 \(A\) 的点的个数为 \(sz_A\),属于 \(B\) 的点的个数为 \(sz_B\),\(x\) 的祖先中属于 \(A\) 的点的个数为 \(dep_A\),属于 \(B\) 的点的个数为 \(dep_B\)。
那么 \({收益_A}=sz_B-dep_B\),\({收益_B}=sz_A-dep_A\),所以 \({净收益_A}=sz_A+sz_B-(dep_A+dep_B)\),我们发现,其实就是 \(sz-dep\),也就是子树大小减去祖先个数。
记得减去这个点的价格。\(sz-dep-w_x\)。
我们把每个点按净收益排序,两人都按最优策略轮流拿。统计答案即可。
code
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 2e5+5;
int n,fa[N],w[N],sz[N],v[N],b[N],dep[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;}
LL ans;
bool vs[N];
bool cmp(int x,int y) {return v[x]>v[y];}
void dfs(int u,int f)
{
sz[u]=1; dep[u]=dep[f]+1;
for(int i=head[u];i;i=e[i].u)
{
int v=e[i].v;
if(v==f) continue;
dfs(v,u); sz[u]+=sz[v];
}
}
int main()
{
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=2;i<=n;i++) scanf("%d",&fa[i]),add(fa[i],i),add(i,fa[i]);
dfs(1,0);
for(int i=1;i<=n;i++) v[i]=-w[i]+sz[i]-dep[i],b[i]=i;
sort(b+1,b+1+n,cmp);
for(int i=1;i<=n;i++) i&1?ans+=v[b[i]]:0;
printf("%lld\n",ans);
}
闲话
闲话丢失,重写一遍。(幸亏还记的叫什么)
插播一条闲话!!!我也不知道怎么刷到的。。。(重写的闲话还叫闲话吗?)
应用
T3
咕咕咕。。。