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

『模拟赛』暑假集训CSP提高模拟4

时间:2024-07-21 18:52:16浏览次数:8  
标签:ch 集训 int sum CSP ans 节点 模拟 翻转

Rank

一次比一次烂了,鉴定为不写模拟赛记录导致的。

A. White and Black

原题ARC148C

被自己误导了,导致菊花和链的部分分没拿到。

经验++

对于每个点的父节点若有 $ 1 \le f_i \lt i $,则该图构成的菊花图根可能为 \(1\) 或 \(2\),链则不确定首尾。

Subtask 越来越不好判了www

思路

首先比较易得的是,不会出现无解的情况:因为任意一个节点我们都可以通过先翻转自身再翻转所有子节点的方式将其单独翻转。

其次,按暴力的方法找到思路:对于一个点集 \(S\) 内的点 \(m_i\),若他的父节点及以上已经进行了奇数次翻转操作,那么就不需要在该点翻转;若点集 \(S\) 之外的点的父节点及以上进行了奇数次翻转操作,此时该点处于翻转状态,我们需要在这里进行一次翻转操作。设 \(P=\sum_{i=1}^Q M_i\),则暴力的时间复杂度为 \(O(nP)\),显然是会 TLE 的。

考虑到要求反转的点的数量很小,我们尝试着枚举这些点求解。

读入时标记这些点,枚举时判断其父节点是否被标记,若不是意味着我们需要翻转该点,若是则说明他已经被翻转过。我们若仅翻转枚举的该点,那么对答案的贡献应为其子节点的数量之和加上 \(1\)。

简单画个图模拟一下,发现这样做会产生很多次无用操作。我们在翻转一个被标记的节点时,默认将其子节点再次翻回来,也就是上述的操作;如果一个点的父节点被标记,那么此时该点已经被翻转了两次,我们不用再次翻转该节点,且是要在操作其父节点时不将其二次翻转,这样才能得到最优操作次数。因此在遇到父节点被标记的节点时,我们要将答案减去 \(1\)。

细节处理

这道题搬到我们题库上只给了 \(1s\) 的时限,而标记用的数组每次只用了很少的一部分,所以操作完成后手动清零比使用 memset 要快很多。

数据的点集中会有父节点后被标记的情况,所以不能边读边做,要把点集先存下来。

Code:

#include<bits/stdc++.h>

const int Ratio=0;
const int N=2e5+5;
int n,m,tot,ans;
int fx[N],son[N];
int tag[N],s[N];

namespace Wisadel
{
	short main()
	{
		scanf("%d%d",&n,&m);
		for(int i=2;i<=n;i++)
			scanf("%d",&fx[i]),son[fx[i]]++;
		for(int i=1;i<=m;i++)
		{
			scanf("%d",&tot);ans=0;
			for(int j=1;j<=tot;j++)
				scanf("%d",&s[j]),tag[s[j]]=1;
			for(int j=1;j<=tot;j++)
			{
				if(tag[fx[s[j]]]) ans--;
				else ans++;
				ans+=son[s[j]];
			}
			printf("%d\n",ans);
			for(int j=1;j<=tot;j++) tag[s[j]]=0;
		}
		return Ratio;
	}
}
int main(){return Wisadel::main();}

B. White and White

原题C3 放前两个没什么意义。

赛时想到了用和模上 \(p\) 的错解,但由于大样例没过没交,痛失硬控学长的机会。

思路

赛时只想出了 \(O(n^2k)\) 的超级暴力做法,所以从它开始优化吧。

首先,按定义 \(f_{i,j}\) 为到 \(i\) 位分成 \(j\) 段的模 \(p\) 意义下的最小和,则显然有 $f_{i,j}\equiv sum_i\pmod p $。

下面证明直接搬了。

image

Code:

#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(register int (x)=(y);(x)>=(z);(x)--)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{
	char ch=getchar();lx x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#undef lx
#define qr qr()
const int Ratio=0;
const int N=5e5+1;
int n,k,p;
int a[N],sum[N],f[N][101],op[2][101];
namespace Wisadel
{
	short main()
	{
		n=qr,k=qr,p=qr;
		fo(i,1,n)
			a[i]=qr%p,sum[i]=(sum[i-1]+a[i])%p;
		memset(f,0x3f,sizeof f);
		f[0][0]=0;
		fo(i,1,n)
		{
			int fla=(i&1)^1;
			fo(j,1,k)
				f[i][j]=min(f[i][j],f[op[fla][j-1]][j-1]+((sum[i]-sum[op[fla][j-1]])%p+p)%p);
			fo(j,0,k)
			{
				op[i&1][j]=op[fla][j];
				if(f[i][j]<f[op[i&1][j]][j]) op[i&1][j]=i;
			}
		}
		printf("%d\n",f[n][k]);
		return Ratio;
	}
}
int main(){return Wisadel::main();}

C. Black and Black

原题

很神的构造题,赛时想的跟题解差不多,但没时间也没自信考场打出这么复杂的解法。

大体思路是对于每个确定的序列,都能使前缀和后缀同时加或减一个数,加减取决于前缀后缀的正负。我们可以通过调整来实现积的和为零,若无法实现即为无解。

Code:

#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(register int (x)=(y);(x)>=(z);(x)--)

typedef long long ll;
inline int qr()
{
	char ch=getchar();int x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#define qr qr()

const int Ratio=0;
const int N=2e5+1;
int n,k,p;
int a[N];
int pf,pz,sf,sz;
ll ans[N],sum;

namespace Wisadel
{
	void Wgetqianhouzhui()
	{
		int cnt=0;
		fo(i,1,n)
		{
			cnt+=a[i];// 记录前缀
			if(!pf&&cnt<0) pf=i;
			// 前缀和为负 记录
			if(!pz&&cnt>0) pz=i;
			// 为正同理
			if(pz&&pf) break;
		}
		cnt=0;
		fu(i,n,1)
		{
			cnt+=a[i];// 记录后缀
			if(!sf&&cnt<0) sf=i;
			if(!sz&&cnt>0) sz=i;
			if(sz&&sf) break;
		}
	}
	short main()
	{
		n=qr;
		fo(i,1,n)
		{
			a[i]=qr;
			ans[i]=i,sum+=a[i]*ans[i];
			// 赋初值
		}
		Wgetqianhouzhui();
		int pre=0,suf=0;
		if(sum<0) sum=-sum,pre=pf,suf=sz;
		else if(sum>0) pre=pz,suf=sf;
		// 首先 前缀只能统一减小,后缀只能统一增大
		// 关键 如果当前和为负,我们需要往大了调整
		// 方案为负的前缀统一缩小 或 正的后缀统一增大
		// 和为正,就要调小
		// 方案为正的前缀缩小 或 负的后缀增大
		if(sum)
		{
			if(pre) fo(i,1,pre) ans[i]-=sum;
			else if(suf) fo(i,1,suf) ans[i]+=sum;
			else
			{
				printf("No\n");
				return Ratio;
			}
		}
		printf("Yes\n");
		fo(i,1,n) printf("%lld ",ans[i]);
		return Ratio;
	}
}
int main(){return Wisadel::main();}

D. Black and White

逆天题,改完再写。


完结撒花~

标签:ch,集训,int,sum,CSP,ans,节点,模拟,翻转
From: https://www.cnblogs.com/Ratio-Yinyue1007/p/18314824

相关文章

  • 暑假集训csp提高模拟2
    赛时rank11,T130,T20,T320,T420T1活动投票摩尔投票模板题点此查看代码#include<bits/stdc++.h>#include<bits/extc++.h>//usingnamespace__gnu_pbds;//usingnamespace__gnu_cxx;usingnamespacestd;#defineinfile(x)freopen(x,"r",stdin)#define......
  • 7月21号模拟赛赛后总结
    7月21号模拟赛赛后总结\[7月\21号\模拟赛\\赛后总结\\2024年7月21日\\by\\\hcy\]一、做题情况第一题比赛\(10pts\),赛后\(AC\)第二题比赛\(0pts\),赛后\(AC\)第三题比赛\(30pts\),赛后\(AC\)第四题比赛\(0pts\),赛后\(AC\)比赛得分\(40pts\)......
  • 暑假集训CSP提高模拟4
    暑假集训CSP提高模拟4\(T1\)P134.WhiteandBlack\(0pts\)原题:[ARC148C]LightsOutonTree翻转方式:从根节点进行\(DFS\),若遇到黑点就进行翻转。最后一定能使全树均为白点,即不存在无解的情况。进而有每个点仅会被主动翻转一次,且翻转顺序与最终结果无关。观察到......
  • 暑假集训CSP提高模拟4
    A.WhiteandBlack暴力的\(O(nq)\)做法比较显然,因为对于根节点来说,只有它自己可以改变自己的颜色,因此如果它是黑色则一定需要更改自己,同时把更改传下去(应该没有那种每次真的更改所有节点然后写\(O(nqn^{n})\)的吧),同理,假如根节点更改结束,次级节点就同理了,这是一个连锁的反应,因......
  • 2024夏令营提高1模考0721模拟赛(提高1)补题报告
    2024夏令营提高1模考0721模拟赛(提高1)补题报告\[07121模拟赛(提高1)\\\补题报告\\\\2024年7月21日\\\by\\\唐一潇\]一、做题情况第一题比赛\(100/100\),赛后通过第二题比赛\(0/100\),赛后通过第三题比赛\(0/100\),赛后通过第四题比赛\(0/100\)......
  • 「模拟赛」暑期集训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......
  • 我的沙子模拟遇到问题
    我试图在模拟中添加一个空单元,但某些单元没有被检查。我尝试添加一个空单元,但底部和右侧的邻居没有被删除。这是代码:importpygamepygame.init()CELL_SIZE=5WIDTH=1600HEIGHT=900FPS=60BLACK=(0,0,0)SAND_COLOR=(255,255,0)MUD_COLOR=(100,50,......
  • 当值来自函数 python unittest 时,如何模拟全局变量
    我必须在python中模拟全局变量,但变量值来自另一个函数。当我导入文件时,这个函数正在运行,但我想要那里的模拟值。secrets.pyimporttracebackimportloggingimportboto3importosimportjsonlogger=logging.getLogger()logger.setLevel(logging.INFO)secret_......
  • 关闭 contextlib 模块时如何模拟 psycopg2.connect?
    我有以下带有get_data方法的数据库类。它使用“contextlib”模块的“关闭”来关闭连接。classDatabase:def__init__(self)->None:self.db_details={<connectiondetails>}defget_data(self,query,parameters):withclosing(psycopg2......