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。
代码还没写。

浙公网安备 33010602011771号