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

咕咕咕。。。

posted @ 2024-09-05 10:42  ppllxx_9G  阅读(13)  评论(0编辑  收藏  举报