题目地址https://vjudge.net/contest/620054#problem/A
清明节假日不组织晚训,两个任务
1 订正以前晚训的错题
2 尽量做做清明节算法专题VJ
A题
主要是判断往回喝水还是向前走一站再喝水,考虑5的余数即可
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
if(n%5==0)cout<<n;
else if(n%5<=2)cout<<n/5*5;
else cout<<n/5*5+5;
return 0;
}
B题
简单模拟题
#include<bits/stdc++.h>
using namespace std;
int A[50];
int main(){
A[1]=0;
A[2]=A[1]+3;
A[3]=A[2]+1;
A[4]=A[3]+4;
A[5]=A[4]+1;
A[6]=A[5]+5;
A[7]=A[6]+9;
char p,q;
cin>>p>>q;
cout<<abs(A[p-'A'+1]-A[q-'A'+1]);
return 0;
}
C题
至少是一个
2
∗
2
2*2
2∗2的饼干矩形,那么我们直接判断所有的
.
.
.即可
判断有
.
.
.的地方,作为
2
∗
2
2*2
2∗2饼干矩形的哪一个角。注意边界的判断
一定要先判断越界,再判断是什么元素,不要放在一起判断
#include<bits/stdc++.h>
using namespace std;
char s[505][505];
int n,m;
bool check(int x,int y){
//左上
if(y+1<=m&&x+1<=n){
//?*
//**
if(s[x][y+1]==s[x+1][y]&&s[x+1][y]==s[x+1][y+1]&&s[x][y+1]=='#')return true;
}
//右上
if(y-1>=1&&x+1<=n){
//*?
//**
if(s[x][y-1]==s[x+1][y]&&s[x+1][y]==s[x+1][y-1]&&s[x][y-1]=='#')return true;
}
//左下
if(y+1<=m&&x-1>=1){
//**
//?*
if(s[x][y+1]==s[x-1][y]&&s[x-1][y]==s[x-1][y+1]&&s[x][y+1]=='#')return true;
}
//右下
if(y-1>=1&&x-1>=1){
//**
//*?
if(s[x][y-1]==s[x-1][y]&&s[x-1][y]==s[x-1][y-1]&&s[x][y-1]=='#')return true;
}
return false;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>s[i]+1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i][j]=='.'){
bool ok=check(i,j);
if(ok){
cout<<i<<" "<<j;
return 0;
}
}
}
}
return 0;
}
D题
经典的区间询问问题
不难发现本题范围很大,但是N一般般大
A
A
A数组相当于是睡眠的记录数组,偶数位置是开始睡觉的时间,奇数位置是醒来时间,我们可以考虑记录一个睡眠累计时长的前缀和
s
u
m
[
i
]
sum[i]
sum[i]
表示
1
−
−
i
1--i
1−−i 睡眠的总时间
观察
A
[
1
]
,
A
[
2
]
,
A
[
3
]
.
.
.
.
.
A
[
x
]
,
L
,
A
[
x
+
1
]
.
.
.
A
[
y
]
,
R
.
.
A
[
n
]
A[1],A[2],A[3].....A[x],L,A[x+1]...A[y],R..A[n]
A[1],A[2],A[3].....A[x],L,A[x+1]...A[y],R..A[n]
我们查询的时间线
L
,
R
L,R
L,R必定会在
A
A
A数组中呈现如此状态
所以我们考虑二分查找,找到
L
,
R
L,R
L,R在
A
A
A数组中(最接近的不大于的元素位置),有了位置就可以考虑利用前缀和处理。例如我们可以直接计算出
s
u
m
[
x
]
,
s
u
m
[
y
]
sum[x],sum[y]
sum[x],sum[y] ,再根据二分查找得到的下标精确计算出
A
[
x
]
−
−
L
A[x]--L
A[x]−−L的时间里面睡眠了多久(
A
[
x
]
A[x]
A[x]要么是醒来的时间,要么是睡觉的时间点,
A
[
y
]
A[y]
A[y]同理),然后利用减法即可计算出
L
−
−
R
L--R
L−−R分钟睡觉了多久
#include<bits/stdc++.h>
using namespace std;
long long int sum[200005];
long long int A[200005];
bool check(int pos,int vel){
if(A[pos]<=vel)return true;
else return false;
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) {
cin>>A[i];
if(i%2==1){
sum[i]=sum[i-1]+(A[i]-A[i-1]);//睡眠前缀和
}
else sum[i]=sum[i-1];
}
int q;
cin>>q;
while(q--){
int l,r;
cin>>l>>r;
int L=1,R=n;
int pos_L,pos_R;
while(L<R){
int mid=(R+L+1)/2;
if(check(mid,l)){
L=mid;
}
else{
R=mid-1;
}
}
pos_L=L;
L=1,R=n;
while(L<R){
int mid=(R+L+1)/2;
if(check(mid,r)){
L=mid;
}
else{
R=mid-1;
}
}
pos_R=L;
long long int time_L;
long long int time_R;
if(pos_L%2==0){
time_L=sum[pos_L]+l-A[pos_L];
}
else{
time_L=sum[pos_L];
}
if(pos_R%2==0){
time_R=sum[pos_R]+r-A[pos_R];
}
else{
time_R=sum[pos_R];
}
cout<<time_R-time_L<<'\n';
}
return 0;
}
E题
简单语法题,输出有点小技巧会方便点,像一般遇到环状的数据,我们考虑把数据从0位置存入
#include<bits/stdc++.h>
using namespace std;
struct pe{
int year;
char name[30];
}A[110];
int main(){
int n;
scanf("%d",&n);
int mi=1e9;
int pos;
for(int i=0;i<n;i++){
scanf("%s%d",A[i].name+1,&A[i].year);
if(A[i].year<mi){
mi=A[i].year;
pos=i;
}
}
printf("%s\n",A[pos].name+1);
int now=(pos+1)%n;
while(now!=pos){
printf("%s\n",A[now].name+1);
now=(now+1)%n;
}
return 0;
}
F题
本题方法很多,我用的是“递减”思维
n
n
n只要
≥
≥
≥ 10 3 就要截断,统计截断了多少次,就输出的时候补0
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int base=1000;
int ok=0;
for(int i=1;i<=6;i++){
if(n>=base)n=n/10,ok++;
}
cout<<n;
for(int i=1;i<=ok;i++)cout<<0;
return 0;
}
G题
临时加的一道题目,担心本套晚训题目组的太简单了QAQ
一个一个枚举肯定是不行的,必定超时,
我们考虑每个
A
[
i
]
A[i]
A[i]如何来组成贡献
因为差至多为D,而且还要加起来的和尽可能大,实际上最优的答案对于
A
[
i
]
A[i]
A[i]来说就是
A
[
i
]
+
D
A[i]+D
A[i]+D 我们把它当成检查的判断,对排序(从小到大)后的
B
B
B数组进行二分查找,寻找
B
[
m
i
d
]
+
A
[
i
]
≤
A
[
i
]
+
D
B[mid]+A[i]≤A[i]+D
B[mid]+A[i]≤A[i]+D 如果成立,我们尽可能地逼近
A
[
i
]
+
D
A[i]+D
A[i]+D 也就是我们需要把答案范围朝着大的方向变,也就是
L
=
m
i
d
L=mid
L=mid
当然如果找不到解最终要输出-1
#include<bits/stdc++.h>
using namespace std;
long long int A[200005];
long long int B[200005];
int main()
{
int n,m;
long long int d;
cin>>n>>m>>d;
for(int i=1;i<=n;i++){
cin>>A[i];
}
for(int i=1;i<=m;i++){
cin>>B[i];
}
sort(B+1,B+1+m);
long long int ans=0;
for(int i=1;i<=n;i++){
//A[i] A[i]+D
int L=1,R=m;
while(L<R){
int mid=(L+R+1)/2;
if(B[mid]<=A[i]+d){
L=mid;
}
else{
R=mid-1;
}
}
long long int now=A[i]-B[L];
if(now<0)now=-now;
if(now<=d&&A[i]+B[L]>ans){
ans=A[i]+B[L];
}
}
if(ans==0){
cout<<-1;
}
else cout<<ans;
return 0;
}
每日积累的知识,每天放弃的娱乐时间,势必化成我前进的力量