某模拟赛

A.病毒传播

1s

Description

培养皿可以看作一个m行n列的网格。
初始时一些格子放有病毒。
有两种病毒,第一种是ALPHA病毒,它的特点是如果一个格子四连通与ALPHA病毒相连,那么这个格子第二天也会感染ALPHA病毒。 第二种是DELTA病毒,它的特点是如果一个格子八连通与DELTA病毒相连,那么这个格子第二天也会感染DELTA病毒。
一个格子如果感染了ALPHA病毒或DELTA病毒,那么这个病毒会永久存在在这个格子当中。两种病毒可以在同一个格子中共存。
现在小Z想问问你,T天过去以后,哪些格子里有病毒。
ps. 四连通指格子的上下左右相邻,八连通为上下左右,左上,右上,左下,右下相邻。

\(1\leq n,m\leq 500,1\leq T\leq 10^9\)

Solution

模拟即可(全部感染时提前break),复杂度\(O(n^3)\)

Code

#include<bits/stdc++.h>
using namespace std;
int read(){
	int w=0,f=1;char c=getchar();
	while (c<'0'||c>'9'){
		if (c=='-') f=-1;
		c=getchar();
	}
	while (c>='0'&&c<='9'){
		w=w*10+c-'0';
		c=getchar();
	}
	return w*f;
}
const int N=505;
int n,m,T,a[N][N],cnt;
void solve(int x,int y,int k){
	if(k==2){
		if(x-1>0) if(!a[x-1][y]) ++cnt,a[x-1][y]=2;else a[x-1][y]=2;
		if(y-1>0) if(!a[x][y-1]) ++cnt,a[x][y-1]=2;else a[x][y-1]=2;
		if(x+1<=n)if(!a[x+1][y]) ++cnt,a[x+1][y]=2;else a[x+1][y]=2;
		if(y+1<=m)if(!a[x][y+1]) ++cnt,a[x][y+1]=2;else a[x][y+1]=2;
		if(x-1>0&&y-1>0)  if(!a[x-1][y-1]) ++cnt,a[x-1][y-1]=2;else a[x-1][y-1]=2;
		if(y-1>0&&x+1<=n) if(!a[x+1][y-1]) ++cnt,a[x+1][y-1]=2;else a[x+1][y-1]=2;
		if(x+1<=n&&y+1<=m)if(!a[x+1][y+1]) ++cnt,a[x+1][y+1]=2;else a[x+1][y+1]=2;
		if(y+1<=m&&x-1>0) if(!a[x-1][y+1]) ++cnt,a[x-1][y+1]=2;else a[x-1][y+1]=2;
	}
	if(k==1){
		if(x-1>0 &&!a[x-1][y]) ++cnt,a[x-1][y]=1;
		if(y-1>0 &&!a[x][y-1]) ++cnt,a[x][y-1]=1;
		if(x+1<=n&&!a[x+1][y]) ++cnt,a[x+1][y]=1;
		if(y+1<=m&&!a[x][y+1]) ++cnt,a[x][y+1]=1;
	}
}
queue<pair<pair<int,int>,int> > q;
pair<pair<int,int>,int> mtlyk(int qa,int qb,int qc){return make_pair(make_pair(qa,qb),qc);}
void bfs(){
	for(int i=1;i<=n;++i)	
		for(int j=1;j<=m;++j)
			if(a[i][j])
				q.push(mtlyk(i,j,a[i][j]));
	while(!q.empty()){solve(q.front().first.first,q.front().first.second,q.front().second);q.pop();}
}
int main(){
	n=read();m=read();T=read();char c;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			{cin>>c;if(c=='A') a[i][j]=1,++cnt;if(c=='D') a[i][j]=2,++cnt;}
	while(T--){bfs();if(cnt==n*m) break;}
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j)
			printf("%d ",(a[i][j]?1:0));
		printf("\n");
	}
	return 0;
}

B.双倍逆序

1s

Description

给定一个\(n\)个数字的序列\(a_1, a_2, \ldots, a_n\) ,问双倍逆序对的数量是多少。
双倍逆序对的定义如下,一组(i,j)满足\(i<j,a_i > 2 a_j\)为一对双倍逆序对。

\(1\leq n\leq 10^5,1\leq a_i \leq 10^8\)

Solution

归并排序求逆序对,魔改一下就行了,复杂度\(O(n\log n)\)

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
int read(){
	int w=0,f=1;char c=getchar();
	while (c<'0'||c>'9'){
		if (c=='-') f=-1;
		c=getchar();
	}
	while (c>='0'&&c<='9'){
		w=w*10+c-'0';
		c=getchar();
	}
	return w*f;
}
const int N=100005;
int sortme[N],n,a[N],ans,cnt;
void msor(int l,int r){
	//cout<<l<<r<<' ';
	if(l==r) return;
	int mid=((l+r)>>1);
	msor(l,mid);msor(mid+1,r);
	for(int i=mid+1,j=l;i<=r;++i){
		while(a[j]>(a[i]<<1)&&j<=mid) ++j;
		ans+=j-l;
	}
	int j=l;cnt=0;
	for(int i=mid+1;i<=r;++i){
		while(a[j]>a[i]&&j<=mid) sortme[cnt++]=a[j++];
		sortme[cnt++]=a[i];
	}
	while(j<=mid) sortme[cnt++]=a[j++];
	//for(int i=0;i<cnt;++i) cout<<sortme[i]<<' '; cout<<l<<r<<endl;
	for(int i=0;i<cnt;++i) a[l+i]=sortme[i];
	return;
}
signed main(){
	n=read();
	for(int i=1;i<=n;++i) a[i]=read();
	msor(1,n);
	//for(int i=1;i<=n;++i) printf("%lld ",a[i]);
	printf("%lld",ans);
	return 0;
}

C.MaxGCD

1s

Description

\(gcd(S)\) 表示集合\(S\)中所有元素的GCD。给定可重集\(A\)\(Q\)次询问,每次给定整数\(k\),求

\[max_{S\subseteq A,|S|=k} gcd(S) \]

\(2\leq n\leq 5e5,1\leq a_i\leq 10^6,1\leq Q\leq n,2\leq k\leq n\)

Solution

\(M=max_i a_i\)
枚举[1,M]中的整数(记为\(i\)),枚举\(i\)的倍数,统计\(A\)\(i\)倍数的个数。记tot[i]表示\(A\)\(i\)倍数的个数。
ans[i]表示\(k\)\(i\)时的答案。有\(ans[i]\geq j(i\leq tot[j]) 倒序枚举\)i\(,每次将ans[last+1]~ans[tot[i]]赋值为\)i\(即可。 复杂度\)O(n\ln n)$

Code

#include<bits/stdc++.h>
using namespace std;

int read(){
	int w=0,f=1;char c=getchar();
	while (c<'0'||c>'9'){
		if (c=='-') f=-1;
		c=getchar();
	}
	while (c>='0'&&c<='9'){
		w=w*10+c-'0';
		c=getchar();
	}
	return w*f;
}
int mxtot=1,n,Q,maxx,t[1000006],tot[1000006],ans[500005];
int main(){
	n=read();Q=read();
	for(int i=1,a;i<=n;++i) a=read(),maxx=max(maxx,a),++t[a];
	for(int i=maxx;i>0;--i){
		for(int j=i;j<=maxx;j+=i)
			tot[i]+=t[j];
		for(int j=mxtot+1;j<=tot[i];++j) ans[j]=i;
		mxtot=max(mxtot,tot[i]);
	}
	while(Q--){printf("%d\n",ans[read()]);}
	return 0;
}

D.旅游路线

3s

Description

小Z所在的国家有n个城市,这n个城市之间由无向道路相连,并且任意两个不同的城市之间有且仅有一条路径连接。
APP预设了k个旅行路线,每个旅行路线都是一条路径,每条路径p->q由一个起点p和一个终点q定义,代表着旅行路线为通过无向道路不经过重复点从城市p出发前往城市q。 这k条路径分别有互不相同的推荐值w[i]。推荐值越高表示这条路径越被推荐。
由于疫情的原因,一些城市会封城,无法通行。在本题中,同时只会有一个城市爆发疫情。
现在小Z想添加一个功能,当给定封城城市时,在所有可成行的路径中推荐值在[L,R]区间内APP最推荐的路径是哪条。
你需要实现这个功能,并多次回答相互独立的询问(即,每次询问中封城的城市以该次询问为准)。
如果APP有最推荐的路径,请输出最推荐路径的推荐值。如果没有路径可以推荐,请输出-1。

Solution

Code

posted @ 2021-07-24 23:42  _Veritas  阅读(106)  评论(4编辑  收藏  举报