赛场上完成度: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。
代码还没写。