2022牛客寒假算法基础集训营2

赛场上完成度:9/13

rank:20

A

https://ac.nowcoder.com/acm/contest/23477/A

一个比较愚蠢的办法,假定只用x张伤害法术,显然可以造成的伤害是一个区间,因此每次二分找到最小的大于等于询问值的区间右端点,判断询问值是否被左端点包含即可。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	long long n,m,k;
	scanf("%lld%lld%lld",&n,&m,&k);
	n=min(n,m+1);
	long long mn=n*n,mx=(m+1+m+n)*n/2;
	for (int i=1;i<=k;i++)
	{
		long long x;
		scanf("%lld",&x);
		long long l=1,r=n,fl=0;
		while (l<=r)
		{
			long long mid=l+r>>1;
			if ((m+1+m+mid)*mid/2>=x)
			{
				if (x>=mid*mid) 
				{
					fl=1;
					break;
				}
				r=mid-1;
			}else l=mid+1;
		}
		if (fl) printf("YES\n");
		else printf("NO\n");
	}
		
}

B

https://ac.nowcoder.com/acm/contest/23477/B

两点相连之后,它们的变化量一致,因此在相连之前,必须自行变化至剩余变化量相同才行。

因此考虑对点权排序,从大到小考虑,每次加入一个点,则之前所有块都要变为与当前点权值相同。

具体看代码

#include<bits/stdc++.h>
using namespace std;
const int M=6e6+10;
struct aa
{
	int x,y,z;	
}e[M],b[M];
bool cmp(aa x,aa y)
{	
	return x.z<y.z;
}
int a[M],f[M];
int tot=0,ne[M],he[M],t[M];
void link(int x,int y)
{
	tot++;
	ne[tot]=he[x];
	he[x]=tot;
	t[tot]=y;	
}
int get(int x)
{
	if (f[x]==x) return x;
	return f[x]=get(f[x]);	
}
bool c1(aa x,aa y)
{
	return x.z>y.z||(x.z==y.z&&x.x>y.x);	
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	//for (int i=1;i<=n;i++) scanf("%d",&a[i]),f[i]=i;
	for (int i=1;i<=n;i++) scanf("%d",&b[i].z),b[i].x=i,f[i]=i;
	//sort(b+1,b+n+1,c1);
	for (int i=1;i<=m;i++) 
	{
		//scanf("%d%d",&e[i].x,&e[i].y);
		//e[i].z=abs(a[e[i].x]-a[e[i].y]);
		int x,y;
		scanf("%d%d",&x,&y);
		if (x==y) continue;
		if (b[x].z<b[y].z||(b[x].z==b[y].z&&x<y)) link(x,y);
		if (b[x].z>b[y].z||(b[x].z==b[y].z&&x>y)) link(y,x);
	}
	sort(b+1,b+n+1,c1);
/*	for (int i=1;i<=n;i++)
	{
		m++;
		e[m].x=i;
		e[m].y=n+1;
		e[m].z=a[i];	
	}*/
	//sort(e+1,e+m+1,cmp);
	long long gc=0,la=1e9+7,ans=0;
	for (int i=1;i<=n;i++)
	{
		ans=ans+(la-b[i].z)*gc;
		gc++;
		for (int j=he[b[i].x];j;j=ne[j]) 
		{
			int x=get(b[i].x),y=get(t[j]);
			if (x!=y)
			{
				f[x]=y;
				gc--;
			}
		}
		la=b[i].z;
	}
	ans=ans+gc*b[n].z;
	/*long long ans=0;
	for (int i=1;i<=m;i++)
	{
		int x=get(e[i].x),y=get(e[i].y);
		if (x!=y) ans=ans+e[i].z;
		f[x]=y;
	}*/
	printf("%lld\n",ans);
}

C

https://ac.nowcoder.com/acm/contest/23477/C

非常简单的题目。

能扣就扣。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	long long x,a,b;
	scanf("%lld%lld%lld",&x,&a,&b);
	char s[1000010];
	scanf("%s",s+1);
	int n=strlen(s+1),ans=0;
	for (int i=1;i<=n;i++) 	
	{
		if (s[i]=='1'&&x>=a) x=x-a,ans++;
		else x=x+b;
	}
	printf("%d\n",ans);
}

D

https://ac.nowcoder.com/acm/contest/23477/D

首先结论,除了n%3==0,其余都可行。

具体构造方法,每次使用2*3的组合,使边长缩小4或者6。

代码还没写。

 

上一篇:【案例分析】轮胎橡胶经销体系数字化平台开发案例


下一篇:ACM对抗赛有感