首页 > 其他分享 >2024.7.12 模拟赛

2024.7.12 模拟赛

时间:2024-07-14 10:19:04浏览次数:7  
标签:12 return 2024.7 int res LL long fa 模拟

模拟赛

T1 挂 \(70pts\),T2 \(\mathbb{AC}\) 力挽狂澜,T3 暴力爆零,T4 \(5min = 30pts\)。

T1 Cow Toll Paths G

弗洛伊德,跑的过程记最大点权。注意有后效性,需要迭代一下。

按点权排序后再跑可以不用迭代,因为一定会先更新小的,再更新大的。

注意是:变量名别写错???

code
#include<bits/stdc++.h>
using namespace std;
const int N = 305;
#define LL long long
int n,m,q;
LL mp[N][N],mx[N][N];
int main()
{
//	freopen("path.in","r",stdin);
//	freopen("path.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=n;i++) scanf("%lld",&mx[i][i]);
	memset(mp,0x3f,sizeof(mp));
	for(int i=1;i<=n;i++) mp[i][i]=0;
	for(int i=1;i<=m;i++)
	{
		int x,y;LL w; scanf("%d%d%lld",&x,&y,&w);
		mp[x][y]=mp[y][x]=min(mp[x][y],w); mx[x][y]=mx[y][x]=max(mx[x][x],mx[y][y]);
	}
	for(int g=1;g<=5;g++)
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(mp[i][k]+mp[k][j]+max(mx[i][k],mx[k][j])<mp[i][j]+mx[i][j])
				{
					mx[i][j]=max(mx[i][k],mx[k][j]);
					mp[i][j]=mp[i][k]+mp[k][j];
				}
			}
		}
	}
	while(q--)
	{
		int x,y; scanf("%d%d",&x,&y);
		if(mp[x][y]>1e18) printf("%d\n",-1);
		else printf("%lld\n",mp[x][y]+mx[x][y]);
	}
	return 0;
}

T2 [POI2008] KUP-Plot purchase

对于 \(\gt 2k\) 的一定不可能被选中,\(\le k\) 的才有可能被选,所以我们可以把它转化为 \(0/1\) 矩阵,其中不合法的为 \(0\),合法的为 \(1\)。

这显然是一道和最大矩形类似的题,用单调栈和二维前缀和维护,先找出以每一行为起点向上延申的最大矩形。

因为每个合法个体都 \(\lt k\),所以我们如果能找到一个 \(\ge 2k\) 的矩形,那么说明一定会包含一个 \(k \le \&\& \le 2k\) 的合法矩形。

那么如何去确定这个合法矩形呢?

由于我们是从上到下一行一行遍历的,所以显然有以下性质:如果矩形 \(\ge 2k\),那么最终的合法矩形一定会出现在最下面一行中。

证明:由于我们已经判断过除了最后一行——也就是上面的矩形一定是 \(\lt k\) 的(否则就合法输出了)。而加上最后一行就 \(\ge 2k\) 了,所以最后加的这一行一定 \(\ge k\)。

反正只有一行,暴力就好了。(好像能卡?)

单调栈写的有点丑

code
#include<bits/stdc++.h>
using namespace std;
const int N = 2005;
#define LL long long
int n,rb[N][N],lb[N][N],s[N][N];
LL a[N][N],k,sum[N][N];
bool mp[N][N];
int main()
{
//	freopen("matrix.in","r",stdin);
//	freopen("matrix.out","w",stdout);
	scanf("%d%lld",&n,&k);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			scanf("%lld",&a[i][j]);
			if(a[i][j]>=k&&a[i][j]<=2ll*k)
			{
				printf("%d %d %d %d\n",i,j,i,j);
				return 0;
			}
			else if(a[i][j]<k) mp[i][j]=1;
			else if(a[i][j]>2ll*k) mp[i][j]=0;
			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(mp[i][j]) s[i][j]=s[i-1][j]+1;
			else s[i][j]=0;
		}
	}
	for(int i=1;i<=n;i++)
	{
		stack<int> st;
		for(int j=1;j<=n+1;j++)
		{
			while(!st.empty()&&s[i][j]<s[i][st.top()]) 
			{
				rb[i][st.top()]=j-1;
				st.pop();
			}
			st.push(j);
		}
		while(!st.empty()) st.pop();
		for(int j=n;j>=0;j--)
		{
			while(!st.empty()&&s[i][j]<s[i][st.top()])
			{
				lb[i][st.top()]=j+1;
				st.pop();
			}
			st.push(j);
		}
		for(int j=1;j<=n;j++)
		{
			LL ss=sum[i][rb[i][j]]-sum[i-s[i][j]][rb[i][j]]-sum[i][lb[i][j]-1]+sum[i-s[i][j]][lb[i][j]-1];
			if(ss>=k)
			{
				if(ss<=2ll*k)
				{
					printf("%d %d %d %d\n",i-s[i][j]+1,lb[i][j],i,rb[i][j]);
					return 0;
				}
				else
				{
					for(int h=lb[i][j]+1;h<=rb[i][j];h++)
					{
						int g=sum[i][h]-sum[i][lb[i][j]-1];
						if(g>=k&&g<=2*k) 
						{
							printf("%d %d %d %d\n",i,lb[i][j],i,h);
							return 0;
						}
					}
				}
			}
		}
	}
	printf("-1\n");
	return 0;
}

T3 [CF1114F] Please, another Queries on Array?

复习欧拉函数:

\[\varphi(n)=n \prod_i \frac{p_i-1}{p_i} \tag{1} \]

\(p\) 为 \(n\) 的质因子。只用算一次!!!而不是完全分解定理。

  • 如果两个数互质,\(\varphi(n)\) 满足 \(\varphi(x \times y)=\varphi(x) \times \varphi(y)\)

  • 如果两个数不互质,那么只能求出质因子的并集,然后硬算(好像没有特别通用的结论)。

因此我们从式子入手,既然最后维护的是乘积,我们可以把 \((1)\) 拆成两部分,一部分只有 \(n\) 的乘积,另一部分需要维护 \(n\) 的乘积的质因子。

乘积很好维护,线段树即可。而质因子不太好处理。

我们注意到数据范围只有 \(300\),而 \(300\) 以内的质数只有 \(62\) 个!!!刚好和 long long 的长度一致,于是我们想到long long 状压

直接用一个数记录状态,而最后统计答案可以用预处理的 \(\frac{p_i-1}{p_i}\),复习线性求逆元。

坑点较多:

  • 乘积和状压可以一棵树,但是 \(lazy\) 标记要用两个,因为一个涉及 \(mod\)。

  • 状压从 \(0\) 位开始,并且 long long 必须用 1ll<<i-1

  • 区间修改是乘 \(n^{len}\),而不是 \(n\)。

code
#include<bits/stdc++.h>
using namespace std;
const int N = 4e5+5,mod = 1e9+7;
#define LL long long
int n,a[N],q;
int prim[N],cnt;
LL nv[N],pv[N];
bool vs[N];
void pre()
{
	for(int i=2;i<=300;i++)
	{
		if(!vs[i]) prim[++cnt]=i;
		for(int j=1;j<=cnt&&i*prim[j]<=300;j++)
		{
			vs[i*prim[j]]=1;
			if(i%prim[j]==0) break;
		}
	}
	nv[1]=1;
	for(int i=2;i<=300;i++)
		nv[i]=(mod-mod/i)*nv[mod%i]%mod;
	for(int i=1;i<=cnt;i++)
		pv[i]=(prim[i]-1)*1ll*nv[prim[i]]%mod;
}
LL qpow(LL a,LL b)
{
	LL res=1;
	while(b)
	{
		if(b & 1) res=res*a%mod;
		a=a*a%mod; b>>=1;
	}
	return res;
}
LL cal(int k)
{
	LL res=0;
	for(int i=1;i<=cnt&&k!=1;i++)
	{
		if(k%prim[i]==0) res+=(1ll<<(i-1));
		while(k%prim[i]==0) k/=prim[i];
	}
	return res;
}

struct T
{
	int l,r;
	LL p,lz2,ck=1,lz1=1;
} tr[N<<2];

void up(int k) {tr[k].ck=tr[k<<1].ck*tr[k<<1|1].ck%mod; tr[k].p=tr[k<<1].p|tr[k<<1|1].p;}
void down(int k)
{
	if(tr[k].lz1!=1)
	{
		tr[k<<1].ck=tr[k<<1].ck*qpow(tr[k].lz1,tr[k<<1].r-tr[k<<1].l+1)%mod;
		tr[k<<1|1].ck=tr[k<<1|1].ck*qpow(tr[k].lz1,tr[k<<1|1].r-tr[k<<1|1].l+1)%mod;
		tr[k<<1].lz1=tr[k<<1].lz1*tr[k].lz1%mod;
		tr[k<<1|1].lz1=tr[k<<1|1].lz1*tr[k].lz1%mod;
		tr[k].lz1=1;
	}
	if(tr[k].lz2)
	{
		tr[k<<1].p|=tr[k].lz2;
		tr[k<<1|1].p|=tr[k].lz2;
		tr[k<<1].lz2|=tr[k].lz2;
		tr[k<<1|1].lz2|=tr[k].lz2;
		tr[k].lz2=0;
	}
}
void bui(int k,int l,int r)
{
	tr[k].l=l; tr[k].r=r;
	if(l==r) return tr[k].ck=a[l],tr[k].p=cal(a[l]),void(0);
	int mid=l+r>>1;
	bui(k<<1,l,mid); bui(k<<1|1,mid+1,r);
	up(k);
}
void mdf(int k,int l,int r,int v)
{
	if(l<=tr[k].l&&tr[k].r<=r)
	{
		LL tmp=cal(v),tmp2=qpow(v,tr[k].r-tr[k].l+1);
		tr[k].ck=tr[k].ck*tmp2%mod;
		tr[k].p|=tmp;
		tr[k].lz2|=tmp;
		tr[k].lz1=tr[k].lz1*v%mod;
		return;
	}
	down(k);
	int mid=tr[k].l+tr[k].r>>1;
	if(l<=mid) mdf(k<<1,l,r,v);
	if(r>mid) mdf(k<<1|1,l,r,v);
	up(k);
}
LL quec(int k,int l,int r)
{
	if(l<=tr[k].l&&r>=tr[k].r) return tr[k].ck;
	down(k);
	int mid=tr[k].l+tr[k].r>>1;LL res=1;
	if(l<=mid) res=res*quec(k<<1,l,r)%mod;
	if(r>mid) res=res*quec(k<<1|1,l,r)%mod;
	return res;
}
LL quep(int k,int l,int r)
{
	if(l<=tr[k].l&&r>=tr[k].r) return tr[k].p;
	down(k);
	int mid=tr[k].l+tr[k].r>>1;LL res=0;
	if(l<=mid) res|=quep(k<<1,l,r);
	if(r>mid) res|=quep(k<<1|1,l,r);
	return res;
}
int main()
{
//	freopen("array.in","r",stdin);
//	freopen("array.out","w",stdout);
	pre();
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	bui(1,1,n);
	while(q--)
	{
		string c; cin>>c;
		if(c[0]=='M')
		{
			int x,y,z; scanf("%d%d%d",&x,&y,&z);
			mdf(1,x,y,z);
		}
		else 
		{
			int x,y; scanf("%d%d",&x,&y);
			LL res=quec(1,x,y),p=quep(1,x,y);
			for(int i=1;p;i++)
			{
				if(p&1) res=res*pv[i]%mod;
				p>>=1;
			}
			printf("%lld\n",res);
		}
	}
	return 0;
}

T4 ODW

明显 LCA,倍增跳。学到新知识:根号分治!!!

就是步长较大的暴跳,一共跳不了几次。步长较小的可以预处理。

复习 LCA。预处理用树上差分,\(v_{u,c}\) 类似前缀和维护从 \(u\) 开始,步长为 \(c\) 到根的权值和。

注意的就是书上差分要考虑某一段不能整除 \(c\) 的情况,需要取整并向上多跳一个步长满足差分。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 50005,B = 20;
int n,m,a[N],b[N];
int lg[N];//preprocess log
int fa[20][N],dep[N] ,va[B][N];

int tot,head[N];
struct E {int u,v;} e[N<<1];
void add(int u,int v) {e[++tot]={head[u],v}; head[u]=tot;}

int kth(int u,int k)
{
	for(int i=lg[k];i>=0;i--) if(k>>i&1) u=fa[i][u];
	return u;
}
int lca(int x,int y)
{
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=17;i>=0;i--) if(dep[fa[i][x]]>=dep[y]) x=fa[i][x];
	if(x==y) return x;
	for(int i=17;i>=0;i--) if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y];
	return fa[0][x];
}
void dfs(int u,int f)
{
	dep[u]=dep[f]+1; fa[0][u]=f;
	for(int i=1;i<=lg[dep[u]];i++) fa[i][u]=fa[i-1][fa[i-1][u]];
	for(int i=1,v=f;i<B;i++,v=fa[0][v]) va[i][u]=a[u]+va[i][v];
	for(int i=head[u];i;i=e[i].u)
	{
		int v=e[i].v; if(v==f) continue;
		dfs(v,u);
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<n;i++)
	{
		int x,y; scanf("%d%d",&x,&y);
		add(x,y); add(y,x);
	}
	dfs(1,0);
	for(int i=1;i<=n;i++) scanf("%d",&b[i]);
	for(int i=1;i<n;i++)
	{
		int c,u=b[i],v=b[i+1]; scanf("%d",&c);
		int d=lca(u,v),res=0;
		if(c>=B)
		{
			res=a[u]+a[v];
			while(1)//voilently jump
			{
				if(dep[u]<dep[v]) swap(u,v);
				int anc=kth(u,c);
				if(dep[anc]<dep[d]) break;
				res+=a[anc]; u=anc;
			}
			if(u==d||v==d) res-=a[d];
		}
		else
		{
			int gap=dep[u]-dep[d];
			int anc=kth(u,gap/c*c+c);//additionally jump one c,for difference
			res+=va[c][u]-va[c][anc];
			gap=dep[v]-dep[d]-1;//delete node d 
			anc=kth(v,gap/c*c+c);
			if(v!=d) res+=va[c][v]-va[c][anc];
		}
		printf("%d\n",res) ;
	}
	return 0;
}

标签:12,return,2024.7,int,res,LL,long,fa,模拟
From: https://www.cnblogs.com/ppllxx-9G/p/18301065

相关文章

  • 【比赛】CSP提高组模拟1
    和初三学长们一起打的比赛,被人家爆杀了。T1最短路20Pts原题CowTollPathsG。正解是按点权排序后跑一遍Floyd,歪解是多迭代几遍。赛时没开longlong\(80\to20\)。点击查看代码#include<bits/stdc++.h>#defineintllusingnamespacestd;typedeflonglongll......
  • mongoDB 报错 MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017 : 一个可行的
    今天启用mongoshell时发现报错如下:尝试数据指令mongod启动服务器也没有作用,上网查询解决方案后发现是没有在service里面启动mongodb服务,启动该服务后再键入mongosh命令即可正常运行mongoshell。具体操作如下:STEP1:win+R➡️输入services.msc➡️确定 STEP2:找到MongoD......
  • 7.12考试总结
    T1动态询问这个题主要考察快速排序求第k小O(n)的时间复杂度完成的方法主要错误原因在于,在一些情况下x与y并不连续,中间可能会各一个数,所以它的k需要注意这道在这个点上卡了很久,大概花费了1h左右,但感觉应该可以更快的解决,主要在于那道题没学好,一直记了一个错误的算法T2财富计算......
  • 12 外键、视图、事务
    外键:foreignkye外键:一张表(表1)中的其中一个字段,保存的值是另外一张表(表2)的主键,那么表1就是从表(具有外键的表),表2就是主表外键表示了2张表中之间的联系,以另外一张表的外键作为主关键字的表是主表,具有此外键的表是主表的从表,设置了外键的表就是从表外键字段必须保证要与其关联的主......
  • GitHub每日最火火火项目(7.12)
    项目名称:public-apis/public-apis项目介绍:这是一个集体列表,包含了各种免费的API。该项目可能致力于收集和整理不同领域的免费API,为开发者提供便利,使其能够更轻松地获取所需的数据和功能。通过使用这些免费的API,开发者可以节省开发成本,提高开发效率,并且能够快速构......
  • 最小数字游戏(Lc2974)——模拟+优先队列(小根堆)、排序+交换
    你有一个下标从 0 开始、长度为 偶数 的整数数组 nums ,同时还有一个空数组 arr 。Alice和Bob决定玩一个游戏,游戏中每一轮Alice和Bob都会各自执行一次操作。游戏规则如下:每一轮,Alice先从 nums 中移除一个 最小 元素,然后Bob执行同样的操作。接着,Bob会将......
  • 【磁力之家】12个非常实用的磁力网站,海量资源,你懂的!
    磁力网站以其丰富的资源、便捷的搜索功能、快速的下载速度以及匿名性和免费资源等优势,成为了用户获取各种文件资源的首选平台,受到了广泛欢迎。丰富的资源库:磁力网站汇集了大量的资源,涵盖了电影、电视剧、音乐、游戏等各种类型的文件。用户可以在这些网站上方便地找到自己感兴......
  • [lnsyoj300/luoguP3224/HNOI2012]永无乡
    题意给定\(n\)个集合,每个集合最开始只包含数\(a_i\),然后进行\(m\)次合并操作。具体地,每次操作将数\(a_i\)所在的集合与数\(a_j\)所在的集合合并。接下来,进行\(q\)次操作,每次操作可能为合并操作与查询操作,合并操作与上述相同,查询操作为查询数\(a_x\)所在的集合中第......
  • 块设备驱动实现--模拟一个块设备
    1、前言        存储层在收到I/O请求后进行数据处理,再给上层应答,本文实现一个实际的块设备驱动。使用Linux5.4为基础,进行框架搭建和功能实现。2、ko模块与编译    首先定义一个init和exit函数,去注册自己的驱动函数模块。#include<linux/module.h>#includ......
  • 解决HBuilder X运行微信小程序模拟器Error: pages.json解析失败
    前言如果已经排查很久了,那这就不是你的问题了,大概率是由于你曾经创建了一个路径,在指定PagePath的时候又指向了这个路径,这个操作本身没有问题。但是,如果你曾经对这个路径修改过了,那编译器就会有问题,来品鉴一下这个错误。16:15:36.772请注意运行模式下,因日志输出、sourcem......