暑假集训CSP提高模拟14

暑假集训CSP提高模拟14

组题人: @H_Kaguya | @LYinMX

T1 P209.BA 30pts

  • 部分分

    • 30pts :输出 i=1main
  • 数形结合,将 {a} 抽象成矩形,烙饼抽象成海报覆盖,最终有 max(maxi=1m{ai},i=1main) 即为所求,注意精度(?)。

    点击查看代码
    int main()
    {
    	ll n,m,x,sum=0,maxx=0,i;
    	cin>>m>>n;
    	for(i=1;i<=m;i++)
    	{
    		cin>>x;
    		sum+=x;
    		maxx=max(maxx,x);
    	}
    	cout<<max(maxx,(sum+n-1)/n)<<endl;
    	return 0;
    }
    

T2 P210. BB 25pts

  • 原题: luogu P9133 [THUPC 2023 初赛] 大富翁

  • 部分分

    • 25pts :枚举所有合法状态, DFS 序加树状数组维护子树内信息,暴力跳父亲,由买方是 A 还是 B 决定取最大值还是最小值转移,因为只能应付 n 很小的数据,所以暴力跳父亲比树剖维护路径信息会快点(?)。、
      • 实测树剖全部 TLE ,实际 O(log2n) 的维护路径信息不如暴力跳父亲的 O(n)

        点击查看代码
        struct node
        {
        	ll nxt,to;
        }e[400010];
        ll head[400010],w[400010],fa[400010],dfn[400010],out[400010],a[400010],vis[400010],tot=0,cnt=0;
        struct BIT
        {
        	ll c[400010];
        	void init()
        	{
        		memset(c,0,sizeof(c));
        	}
        	ll lowbit(ll x)
        	{
        		return (x&(-x));
        	}
        	void add(ll n,ll x,ll val)
        	{
        		for(ll i=x;i<=n;i+=lowbit(i))
        		{
        			c[i]+=val;
        		}
        	}
        	ll getsum(ll x)
        	{
        		ll ans=0;
        		for(ll i=x;i>=1;i-=lowbit(i))
        		{
        			ans+=c[i];
        		}
        		return ans;
        	}
        	ll ask(ll l,ll r)
        	{
        		return getsum(r)-getsum(l-1);
        	}
        }A,B;
        void add(ll u,ll v)
        {
        	cnt++;
        	e[cnt].nxt=head[u];
        	e[cnt].to=v;
        	head[u]=cnt;
        }
        void dfs(ll x)
        {
        	tot++;
        	dfn[x]=tot;
        	for(ll i=head[x];i!=0;i=e[i].nxt)
        	{
        		dfs(e[i].to);
        	}
        	out[x]=tot;
        }
        ll dp(ll pos,ll n,ll sum)
        {
        	if(pos==n+1)
        	{
        		return sum;
        	}
        	else
        	{
        		ll minn=0x7f7f7f7f,maxx=-0x7f7f7f7f,n1,n2,x;
        		if(pos%2==1)
        		{
        			for(ll i=1;i<=n;i++)
        			{
        				if(vis[i]==0)
        				{
        					n1=n2=0;
        					x=i;
        					while(x!=1)
        					{
        						x=fa[x];
        						n2+=(vis[x]==-1);
        					}
        					n1=B.ask(dfn[i],out[i]);
        					vis[i]=1;
        					A.add(n,dfn[i],1);
        					maxx=max(maxx,dp(pos+1,n,sum+n1-n2-w[i]));
        					A.add(n,dfn[i],-1);
        					vis[i]=0;
        				}
        			}
        			return maxx;
        		}
        		else
        		{
        			for(ll i=1;i<=n;i++)
        			{
        				if(vis[i]==0)
        				{
        					n1=n2=0;
        					x=i;
        					while(x!=1)
        					{
        						x=fa[x];
        						n2+=(vis[x]==1);
        					}
        					n1=A.ask(dfn[i],out[i]);
        					vis[i]=-1;
        					B.add(n,dfn[i],1);
        					minn=min(minn,dp(pos+1,n,sum-(n1-n2)));
        					B.add(n,dfn[i],-1);
        					vis[i]=0;
        				}
        			}
        			return minn;
        		}
        	}
        }
        int main()
        {
        	ll n,i;
        	cin>>n;
        	for(i=1;i<=n;i++)
        	{
        		cin>>w[i];
        	}
        	for(i=2;i<=n;i++)
        	{
        		cin>>fa[i];
        		add(fa[i],i);
        	}
        	dfs(1);
        	cout<<dp(1,n,0)<<endl;
        	return 0;
        }
        
  • 正解

    • 买方每次购买一个点都会得到 n1n2wx 个游戏币,相应的对方减少 n1n2 个游戏币即得到 n2n1 个游戏币。
    • 当购买一个点后,给祖先每个点的所属对象(不管是现在还是未来)交一个游戏币,这样的话仍满足题意。那么一个点对答案产生的贡献就是 sizx1(depx1)wx=sizxdepxwx
      • 实际上就是顺序不会影响最终结果。
    • 排序后跳着选即可。
    点击查看代码
    struct node
    {
    	ll nxt,to;
    }e[400010];
    ll head[400010],w[400010],siz[400010],dep[400010],fa[400010],cnt=0;
    void add(ll u,ll v)
    {
    	cnt++;
    	e[cnt].nxt=head[u];
    	e[cnt].to=v;
    	head[u]=cnt;
    }
    void dfs(ll x)
    {
    	siz[x]=1;
    	dep[x]=dep[fa[x]]+1;
    	for(ll i=head[x];i!=0;i=e[i].nxt)
    	{
    		dfs(e[i].to);
    		siz[x]+=siz[e[i].to];
    	}
    }
    int main()
    {
    	ll n,ans=0,i;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		cin>>w[i];
    	}
    	for(i=2;i<=n;i++)
    	{
    		cin>>fa[i];
    		add(fa[i],i);
    	}
    	dfs(1);
    	for(i=1;i<=n;i++)
    	{
    		w[i]=siz[i]-dep[i]-w[i];
    	}
    	sort(w+1,w+1+n);
    	for(i=n;i>=1;i-=2)
    	{
    		ans+=w[i];
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

T3 P211. BC 0pts

  • 部分分都不会打,弃了。

T4 P212. BD 0pts

  • 同上。

总结

  • 赛时历程: 2min 写完 T1 后开始写 T2 ,没看到最优策略所以写的 next_permutation 发现比答案大且不止一种情况后开始写暴搜,写到 9:30 就过小样例了,尝试用树剖优化却不如暴力。然后就开始罚坐加背《蜀道难》。
  • T1 测过大样例后没再造其他数据检验,导致挂了 70pts

后记

  • 最低暴力分数线: 11pts+0pts+{0pts,11pts}+30pts ,除 @xrlong 外全员需要背《蜀道难》, @LYinMX 本来想督促我们打部分分的,结果发现都没打部分分,被迫称有想背的可以找任意学长背。

  • 10:00 左右才下发大样例。

  • 11:00 左右下发了《蜀道难》.zip

  • T1 输入格式错了,赛时没有更改。

  • T3 题面 @LYinMX 少抄了,样例也抄错一个,赛时更改了,发了公告,但没有弹窗提醒导致大部分人都没看到。

posted @   hzoi_Shadow  阅读(86)  评论(3编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
扩大
缩小
点击右上角即可分享
微信分享提示