题目列表
1.A - Robot Cleaner- codeforces Round #763 (Div. 2)
题意:
有个扫地机器人。给出机器人的初始坐标和灰尘坐标。机器人开始只能同时向下和向右走,如果机器人碰到了上下边界,那机器人就改变纵向的方向(比如之前向下走,碰到下边界就向上走),横向同样也如此。问机器人最少多少步能清洁灰尘。
题解:
以x为例,判断给出的灰尘的位置xr和初始位置xd的大小,如果xr大,直接xr-xd,如果xd大,则2*n-xr-xd。同样方法算出y的值,然后取较小者。
解释:
如果能直接到就算最短距离,如果到不了就先算到边缘的距离,然后再算到灰尘的距离,两者相加就是需要走的距离,比较x和y求出的值。
AC代码:
#include <iostream>
#include <string>
#include <string.h>
#include <cmath>
#include <math.h>
#include <iomanip>
#include <cstdio>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define ll long long
int n,m;
int main()
{
// freopen("1.txt","r",stdin);
int t;
int i1,i2,i3,i4,i5;
int bx,by,ex,ey;
cin>>t;
while(t--)
{
cin>>n>>m>>bx>>by>>ex>>ey;
int min1=max(2*n,2*m);
if(ex>=bx) min1=min(min1,ex-bx);
else min1=min(2*n-ex-bx,min1);
if(ey>=by) min1=min(min1,ey-by);
else min1=min(2*m-ey-by,min1);
cout<<min1<<endl;
}
return 0;
}
2.B - Game on Ranges-codeforces Round #763 (Div. 2)
题意:
开始有n个元素分别是1-n按照大小排序的数组。每次操作可以选择一个数组,然后去掉数组中的任意一个元素,然后数组就被分成了两个数组,其中长度为零的数组就没了,最后直到所有元素都没有位置。题目中给出了在进行上述操作步骤中的数组的左右两边元素(数组不是按照操作过程给出)。问每次操作这个数组时所去掉的元素时什么。
题解:
按照数组的区间长度排序。每次按照左边的元素向下找,如果找到有个区间的左元素和它相等,就输出找到区间的右元素的下一个值。如果没找到,就输出这个区间的左元素。
解释:
还原之前操作的步骤。如果在接下来这个区间的左元素出现了,说明删除的是其他元素,又因为咱们是按照区间大小排序的,所有底下的区间一定是删除元素之后得到的,咱们可以大胆的写出删除的元素。
AC代码:
#include <iostream>
#include <string>
#include <string.h>
#include <cmath>
#include <math.h>
#include <iomanip>
#include <cstdio>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define ll long long
struct z{
int first;
int second;
int third;
}a[1005];
int n,m;
bool cmp(z a,z b)
{
if(a.third==b.third) return a.first<b.first;
else return a.third>b.third;
}
int main()
{
// freopen("1.txt","r",stdin);
int t;
int i1,i2,i3,i4,i5;
cin>>t;
while(t--)
{
cin>>n;
for(i1=1;i1<=n;i1++)
{
cin>>a[i1].first>>a[i1].second;
a[i1].third=a[i1].second-a[i1].first;
}
sort(a+1,a+1+n,cmp);
for(i1=1;i1<=n;i1++)
{
for(i2=i1+1;i2<=n;i2++)
{
if(a[i1].first==a[i2].first) {cout<<a[i1].first<<" "<<a[i1].second<<" "<<a[i2].second+1<<endl;break;}
}
if(i2!=n+1) continue;
if(a[i1].second==a[i1].second) {cout<<a[i1].first<<" "<<a[i1].second<<" "<<a[i1].first<<endl;}
else if(i2==n+1) {cout<<a[i1].first<<" "<<a[i1].second<<" "<<a[i1].first<<endl;}
}
cout<<endl;
}
return 0;
}
3.C - Balanced Stone Heaps-codeforces Round #763 (Div. 2)
题解:
二分。用二分算出每次的最小值。因为知道了最小值,所以就可以从最后一个开始算,将多出了一部分给前一个和前两个就可以了。因为实际是从前向后开始算,所以每次给的部分不能超过原来的大小。
AC代码:
#include <iostream>
#include <string>
#include <string.h>
#include <cmath>
#include <math.h>
#include <iomanip>
#include <cstdio>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define ll long long
int n,m;
int a[200010],b[200010];
bool check(int x)
{
int i1,i2,i3,i4,i5;
for(i1=1;i1<=n;i1++)
b[i1]=a[i1];
for(i1=n;i1>=3;i1--)
{
if(b[i1]<x) return 0;
int d=min(a[i1]/3,(b[i1]-x)/3);
b[i1-1]+=d;
b[i1-2]+=2*d;
}
if(b[1]>=x&&b[2]>=x) return 1;
else return 0;
}
int main()
{
// freopen("1.txt","r",stdin);
int t;
int i1,i2,i3,i4,i5;
cin>>t;
while(t--)
{
cin>>n;
int min1=INT_MAX,max1=0;
for(i1=1;i1<=n;i1++)
{
scanf("%d",&a[i1]);
if(a[i1]<min1) min1=a[i1];
if(a[i1]>max1) max1=a[i1];
}
int r=max1,l=min1,mid;
while(l<r)
{
mid=(l+r+1)/2;
if(check(mid))
{
l=mid;
}
else r=mid-1;
}
cout<<l<<endl;
}
return 0;
}