首页 > 其他分享 >暑假集训CSP提高模拟4

暑假集训CSP提高模拟4

时间:2024-07-21 17:42:48浏览次数:4  
标签:suf cnt int 400010 sum pos 集训 暑假 CSP

暑假集训CSP提高模拟4

\(T1\) P134. White and Black \(0pts\)

  • 原题: [ARC148C] Lights Out on Tree

  • 翻转方式:从根节点进行 \(DFS\) ,若遇到黑点就进行翻转。最后一定能使全树均为白点,即不存在无解的情况。进而有每个点仅会被主动翻转一次,且翻转顺序与最终结果无关。

  • 观察到 \(\sum\limits_{i=1}^{q}m_{i} \le 2 \times 10^{5}\) ,考虑枚举黑点。

  • 若点 \(x\) 与父亲节点颜色不同,则会贡献一次翻转;否则则桶记录下每个节点子节点中有多少个黑点,最后减去即可。

    点击查看代码
    struct node
    {
    	int nxt,to;
    }e[400010];
    int head[400010],fa[400010],son[400010],dep[400010],vis[400010],sum[400010],s[400010],cnt=0;
    void add(int u,int v)
    {
    	cnt++;
    	e[cnt].nxt=head[u];
    	e[cnt].to=v;
    	head[u]=cnt;
    }
    void dfs(int x,int father)
    {
    	fa[x]=father;
    	dep[x]=dep[father]+1;
    	for(int i=head[x];i!=0;i=e[i].nxt)
    	{
    		son[x]++;
    		dfs(e[i].to,x);
    	}
    }
    bool cmp(int a,int b)
    {
    	return dep[a]>dep[b];
    }
    int main()
    {
    	int n,q,u,v,m,ans,i,j;
    	cin>>n>>q;
    	for(i=2;i<=n;i++)
    	{
    		cin>>u;
    		v=i;
    		add(u,v);
    	}
    	dfs(1,0);
    	for(i=1;i<=q;i++)
    	{
    		cin>>m;
    		ans=0;
    		for(j=1;j<=m;j++)
    		{
    			cin>>s[j];
    			vis[s[j]]=1;
    		}
    		sort(s+1,s+1+m,cmp);//从深到浅处理,好像不排序也行
    		for(j=1;j<=m;j++)
    		{
    			if(vis[fa[s[j]]]==1)
    			{
    				sum[fa[s[j]]]++;//统计黑点个数
    			}
    			else
    			{
    				ans++;
    			}
    		}
    		for(j=1;j<=m;j++)
    		{
    			ans+=son[s[j]]-sum[s[j]];//统计因翻转变成黑点的白点
    			vis[s[j]]=sum[s[j]]=0;
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    

\(T2\) P137. White and White \(0pts\)

  • 原题: CF958C3 Encryption (hard)

  • 令 \(sum_{i}=\sum\limits_{j=1}^{i}a_{j}\) ,设 \(f_{i,j}\) 表示把前 \(i\) 个数分成 \(j\) 段时的最小价值总和,状态转移方程为 \(f_{i,j}=\min\limits_{h=j-1}^{i-1} \{ f_{h,j-1}+(sum_{i}-sum_{h}) \bmod p \}\) ,边界为 \(f_{0,0}=0\) 。

    • 直接暴力转移的话时间复杂度为 \(O(n^{2}k)\) ,更改枚举顺序加滚动数组优化后仅能通过 \(Subtask1\) 。
  • 题面隐含着一个 \(f_{i,j} \equiv sum_{i} \pmod{p}\) 。进而有对于 \(f_{i,j}\) 的两个决策 \(x,y(x \ne y)\) 一定有 \(f_{x,j-1}+sum_{i}-sum_{x} \equiv f_{y,j-1}+sum_{i}-sum_{y} \equiv sum_{i} \pmod{p}\) ,进而有 \(f_{x,j-1}+(sum_{i}-sum_{x}) \bmod p \equiv f_{y,j-1}+(sum_{i}-sum_{y}) \bmod p \pmod{p}\)

  • 若 \(f_{x,j-1}<f_{y,j-1}\) ,又因为 \(\begin{cases} (sum_{i}-sum_{x}) \bmod p \in [0,p) \\ (sum_{i}-sum_{y}) \bmod p \in [0,p) \end{cases}\) ,有 \(f_{x,j-1}+(sum_{i}-sum_{x}) \bmod p \le f_{y,j-1}+(sum_{i}-sum_{y}) \bmod p\) 。所以取使 \(f_{h,j-1}\) 最小的 \(h\) 进行转移即可。

    • 反证法即可证明。
  • 最终有 \(f_{n,k}\) 即为所求。

    点击查看代码
    ll a[500010],sum[500010],f[500010][2];
    int main()
    {
    	ll n,k,p,minn,pos,i,j;
    	scanf("%lld%lld%lld",&n,&k,&p);
    	for(i=1;i<=n;i++)
    	{
    		scanf("%lld",&a[i]);
    		sum[i]=sum[i-1]+a[i];
    	}
    	f[0][0]=0;
    	for(j=1;j<=k;j++)
    	{
    		minn=f[j-1][(j-1)&1];
    		pos=j-1; 
    		for(i=j;i<=n;i++)
    		{
    			f[i][j&1]=f[pos][(j-1)&1]+(sum[i]-sum[pos])%p;
    			if(f[i][(j-1)&1]<minn)
    			{
    				minn=f[i][(j-1)&1];
    				pos=i;
    			}
    		}
    	} 
    	printf("%lld\n",f[n][k&1]);
    	return 0;
    }
    

\(T3\) P132. Black and Black \(0pts\)

  • 原题: [ARC153C] ± Increasing Sequence

  • 因要满足 \(|b_{i}| \le 2 \times 10^{12}\) ,考虑尽量减小 \(|b_{i}|\) 着填。

  • 先将 \(1 \sim n\) 填入 \(b\) ,记 \(s=\sum\limits_{i=1}^{n}a_{i}b_{i}\) , 然后考虑调整。

  • 当 \(s>0\) 时, 若 \(\{ a \}\) 存在一个前缀和为正数或存在一个后缀和为负数则一定有解。

    • 存在一个前缀和为正数则一定存在一个前缀和等于 \(1\) 。接着将这个前缀减去 \(s\) 就会满足题意。
    • 存在一个后缀和为负数则一定存在一个后缀和等于 \(-1\) 。接着将这个后缀加上 \(s\) 就会满足题意。
  • 当 \(s=0\) 时,直接输出 \(\{ b \}\) 。

  • 当 \(s<0\) 时,同理。

    点击查看代码
    ll a[200010],b[200010],pre[200010],suf[200010];
    int main()
    {
    	ll n,sum=0,flag=0,pos=0,i;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    		b[i]=i;
    		sum+=a[i]*b[i];
    		pre[i]=pre[i-1]+a[i];
    	}
    	for(i=n;i>=1;i--)
    	{
    		suf[i]=suf[i+1]+a[i];
    	}
    	if(sum==0)
    	{
    		cout<<"Yes"<<endl;
    		for(i=1;i<=n;i++)
    		{
    			cout<<b[i]<<" ";
    		}
    	}
    	else
    	{
    		if(sum>0)
    		{
    			for(i=1;i<=n;i++)
    			{
    				flag|=(pre[i]>=1||suf[i]<=-1);
    			}
    			if(flag==0)
    			{
    				cout<<"No"<<endl;
    			}
    			else
    			{
    				for(i=1;i<=n;i++)
    				{
    					if(pre[i]==1)
    					{
    						pos=i;
    						break;
    					}
    				}
    				if(pos==0)
    				{
    					for(i=n;i>=1;i--)
    					{
    						if(suf[i]==-1)
    						{
    							pos=i;
    							break;
    						}
    					}   
    					for(i=pos;i<=n;i++)
    					{
    						b[i]+=sum;
    					}
    				}
    				else
    				{
    					for(i=1;i<=pos;i++)
    					{
    						b[i]-=sum;
    					}
    				}
    				cout<<"Yes"<<endl;
    				for(i=1;i<=n;i++)
    				{
    					cout<<b[i]<<" ";
    				}
    			}
    		}
    		else
    		{
    			for(i=1;i<=n;i++)
    			{
    				flag|=(pre[i]<=-1||suf[i]>=1);
    			}
    			if(flag==0)
    			{
    				cout<<"No"<<endl;
    			}
    			else
    			{
    				for(i=1;i<=n;i++)
    				{
    					if(pre[i]==-1)
    					{
    						pos=i;
    						break;
    					}
    				}
    				if(pos==0)
    				{
    					for(i=n;i>=1;i--)
    					{
    						if(suf[i]==1)
    						{
    							pos=i;
    							break;
    						}
    					}   
    					for(i=pos;i<=n;i++)
    					{
    						b[i]-=sum;
    					}
    				}
    				else
    				{
    					for(i=1;i<=pos;i++)
    					{
    						b[i]+=sum;
    					}
    				}
    				cout<<"Yes"<<endl;
    				for(i=1;i<=n;i++)
    				{
    					cout<<b[i]<<" ";
    				}
    			}
    		}
    	}
    	return 0;
    }
    

\(T4\) P136. Black and White \(0pts\)

总结

  • \(T1\) 以为翻转顺序会影响最终答案,所以要用 \(DP\) 。想到正解后又被自己 \(Pass\) 了。
  • \(T2\)
    • 三个 \(Subtask\) 数据范围有较大差别,以为会像 LibreOJ 6560. 小奇取石子 一样面向数据点分治。
    • 空间又开大了,加上没有进行滚动数组优化,挂了 \(10pts\) 。
  • \(T3\) 赛时以为是类似 初三奥赛模拟测试1 T3 混乱邪恶 一样的高级构造,遂没写。

后记

  • \(T2\) 赛时进行改数据(不捆绑到捆绑)和时限( \(1.5s\) 到 \(0.5s\) ),卡掉了树状数组和一些常数大点的正解做法。
  • \(T3\) 直接下发了可执行文件 \(checker\) ,在 \(Windows\) 下可以正常用,但 \(Linux\) 下少权限,需要 【数据删除】 来获得权限。

标签:suf,cnt,int,400010,sum,pos,集训,暑假,CSP
From: https://www.cnblogs.com/The-Shadow-Dragon/p/18314678

相关文章

  • 暑假训练第二周周报
    总体学习情况这周时间大多花在写上周的堆栈的题单了,然后比赛又碰到了一些新的知识点,比如无权二分图的最大匹配,01背包的相似例题,但是感觉数据结构的基础还是得练,遇到一些题还是没办法写对。知识点模块1.无权二分图最大匹配用通俗的话来讲,假如有几个男的和几个女的存在暧昧关系,......
  • 暑假集训CSP提高模拟4
    A.WhiteandBlack暴力的\(O(nq)\)做法比较显然,因为对于根节点来说,只有它自己可以改变自己的颜色,因此如果它是黑色则一定需要更改自己,同时把更改传下去(应该没有那种每次真的更改所有节点然后写\(O(nqn^{n})\)的吧),同理,假如根节点更改结束,次级节点就同理了,这是一个连锁的反应,因......
  • 「模拟赛」暑期集训CSP提高模拟3(7.20)
    仍在施工...$165pts,Rank18$B题挂了45分,不然可以AC两道题的,呜题目列表:A.abc猜想B.简单的排列最优化题C.简单的线性做法题D.简单的线段树题A.abc猜想题意:给定三个正整数\(a,b,c\),你需要求出\(a^b\)除以\(c\)并向下取整得到的值对\(c\)取模的结果......
  • 暑假集训CSP提高模拟2 & 暑假集训CSP提高模拟3
    暑假集训CSP提高模拟2&暑假集训CSP提高模拟3暑假集训CSP提高模拟2纯纯科普场,打的还行。T1活动投票:摩尔投票板子。T2序列:考虑枚举端点没什么前途,考虑一个点能对多少区间产生贡献。考虑一个点的\(nxt\)和\(pre\)(表示下、上一个和他相同的点),当左端点在\(pre\simi......
  • 24-暑假软件工程周报(3)
    本周,我继续深入学习Hadoop和HBase。在上次报告的基础上,我主要集中在HBase的配置和使用方面,并遇到了一些问题,通过查阅资料和调试成功解决了这些问题。1.我学习了HBase的基本概念和架构。HBase是一个基于HadoopHDFS的分布式数据库,专门用于处理大规模数据的随机读写。它通过Zookeep......
  • 2024 暑假友谊赛 2
    2024暑假友谊赛2A-......
  • 暑假集训csp提高模拟3
    赛时rank20,T10,T245,T320,T495T1粘了两遍(因为OJ卡第一次没有显示出来)CE了,挂了100,T4没卡常挂了5汤碗了!!!!!!!!!!!!!!!T1abc猜想对于任意整数\(c\)都有\[\left\lfloor\frac{a}{b}\right\rfloor+c=\left\lfloor\frac{a}{b}+c\right\rfloor=\left\lfloor\frac{a+bc}{b}\right\rf......
  • 暑假集训记录
    这里记一些从7.15开始做的NOI篇或者让人眼前一亮的题目/trick。(哦,前面的题可能忘了某些细节了。)P3452求补图连通块个数。P4555首先看到回文串,先上马拉车。然后发现马拉车双回文不好做,考虑拆成两部分。大概就是维护一个以\(i\)为左端点/右端点的最长回文串。然后......
  • 暑假学习Java第三周
    通过本周的学习我认识到了自己有很多的不足与优点,优点是我能够把问题细化逐步分析,缺点是我的意志力不够坚定。我还了解了Java的三大特性包括:面向对象:Java是一种面向对象的编程语言,它允许程序员定义一系列关于对象和类的概念,并将这些概念作为编程的基本单位。在实际内容中,面向对象......
  • 2024 暑假友谊赛 2
    A题目链接思路:枚举每个十字中心点,合法就标记,最后若还剩下点没被标记就NO#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definePIIpair<int,int>constintN=1e6+5,mod=998244353,Mod=1e9+7;intdx[4]={-1,0,1,0};intdy[4......