文章目录
[入门赛 #14] 塔台超频 (Hard Version) 题解
题面
思路
一眼二分答案,二分时判断当时电压能不能让信息传导过去。
code
//by MornStar
#include<bits/stdc++.h>
using namespace std;
//以下read与write函数为快读快写
long long n,in[500005],r[500005];
bool check(int x){
long long i=1,j=1;
for(int i=1;i<=j;i++){
if(j==n) return 1;
long long tmp=upper_bound(in+1,in+n+1,in[i]+r[i]+x)-in-1;
j=max(j,tmp);//目前最远能到达的塔台。
}
return 0;
}
int main(){
n=read();
for(int i=1;i<=n;i++){
in[i]=read();
r[i]=read();
}
long long l=0,r=1000000001,ans;
while(l<r){
long long mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
write(l);
}
[入门赛 #14] Three-View Projection (Hard Version) 题解
题面
思路
大膜你,只是输入有点坑。
先对照下面这张图来判断怎么输出。
正视图对应过来应该是 Z 轴从大到小枚举,X 轴从小到大枚举,对于每个点,枚举 Y 轴上是否存在方块。
另外两个视图同理。
注意:输入时循环顺序为 k,n,m。
code
//by MornStar
#include<bits/stdc++.h>
using namespace std;
//以下read与write函数为快读快写
long long n,m,k;
bool f[205][205][205];
int main(){
n=read(),m=read(),k=read();
for(int x=1;x<=k;x++){
for(int y=1;y<=n;y++){
for(int z=1;z<=m;z++){
f[y][z][x]=read();
}
}
}
for(int z=k;z>=1;z--){
for(int x=1;x<=n;x++){
bool flag=0;
for(int y=1;y<=m;y++){
if(f[x][y][z]){
flag=1;
break;
}
}
write(flag,' ');
}
putchar('\n');
}//正视图
for(int z=k;z>=1;z--){
for(int y=m;y>=1;y--){
bool flag=0;
for(int x=1;x<=n;x++){
if(f[x][y][z]){
flag=1;
break;
}
}
write(flag,' ');
}
putchar('\n');
}//左视图
for(int y=m;y>=1;y--){
for(int x=1;x<=n;x++){
bool flag=0;
for(int z=1;z<=k;z++){
if(f[x][y][z]){
flag=1;
break;
}
}
write(flag,' ');
}
putchar('\n');
}//俯视图
}
[入门赛 #14] 魔法少女扶苏 (Hard Version) 题解
题面
思路
对于 a x , y a_{x,y} ax,y,如果其满足要求,即 a x , y ≥ ∑ i = 1 n a i , y + ∑ i = 1 m a x , i a_{x, y} \geq \sum \limits _{i = 1}^n a_{i,y} + \sum \limits _{i = 1}^m a_{x,i} ax,y≥i=1∑nai,y+i=1∑max,i。
则 0 ≥ ∑ i = 1 n a i , y + ∑ i = 1 m a x , i − a x , y 0 \geq \sum \limits _{i = 1}^n a_{i,y} + \sum \limits _{i = 1}^m a_{x,i}-a_{x,y} 0≥i=1∑nai,y+i=1∑max,i−ax,y。
对于每一次操作,不等式右边都会减少 n + m − 1 n+m-1 n+m−1。
所以我们只需要找到第 k k k 小的 ∑ i = 1 n a i , y + ∑ i = 1 m a x , i − a x , y \sum \limits _{i = 1}^n a_{i,y} + \sum \limits _{i = 1}^m a_{x,i}-a_{x,y} i=1∑nai,y+i=1∑max,i−ax,y 计算答案就行了,注意答案要向上取整。
code
//by MornStar
#include<bits/stdc++.h>
using namespace std;
//以下read与write函数为快读快写
long long a[3005][3005],sumh[3005],suml[3005],sum[3005*3005];
int main(){
int n=read(),m=read(),k=read();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
a[i][j]=read();
sumh[i]+=a[i][j];
suml[j]+=a[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
sum[(i-1)*m+j]=sumh[i]+suml[j]-a[i][j];
}
}
sort(sum+1,sum+n*m+1);
write((sum[k]+n+m-2)/(n+m-1));
}
[入门赛 #14] 扶苏和串 (Hard Version)
题面
思路
可以发现,翻转区间的左端点一定是整个字符串从前往后第一个 1 1 1。
翻转区间的右端点一定是一个 0 0 0。
找到第一个 1 1 1,然后依次枚举 0 0 0,找到字典序最小的一个。
反转字符串可以使用题目中给出的公式:
t i = { s i , i < l 或 i > r s r − ( i − l ) , l ≤ i ≤ r t_i = \begin{cases}s_i, &i < l \text{ 或 } i > r \\ s_{r - (i - l)}, & l \leq i \leq r\end{cases} ti={si,sr−(i−l),i<l 或 i>rl≤i≤r
code
//by MornStar
#include<bits/stdc++.h>
using namespace std;
string s,ans;
int l,r;
string get(int l,int r){
if(r<=l){
return s;
}else{
string tmp="";
for(int i=0;i<s.length();i++){
if(i<l||i>r) tmp+=s[i];
else tmp+=s[r-i+l];
}
return tmp;
}
}
int main(){
cin>>s;
ans=s;
for(int i=0;i<s.length();i++){
if(s[i]=='1'){
l=i;
break;
}
}
for(int i=s.length()-1;i>=0;i--){
if(s[i]=='0'){
r=i;
string tmp=get(l,r);
if(tmp<ans) ans=tmp;
}
}
cout<<ans;
}