A. Shifting Stacks
您有n叠积木,第i个堆栈包含hi块,其高度是其中的积木块数。一次移动可以从第i个堆栈中取出一个积木(如果至少有一个)并将其放入第i + 1个堆栈中。您可以使堆栈高度严格递增吗?
注意:堆栈数始终为n,即使堆栈中积木数量为0也不会消失。
思路
我们在构造的过程中使堆栈以0,1,2……n-1的数量排列,只要在过程中检验是否可以达成即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+5;
typedef long long ll;
const int inf=1e9;
ll sum,a[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--)
{
sum=0;
int n;
cin>>n;
bool flag=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=(a[i]-i+1);
if(sum<0)
flag=1;
}
if(!flag)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
B. Eastern Exhibition
您和您的朋友住在n所房屋中,每个房屋都位于2D平面的整数坐标点上,同一地点可能有不同的房屋。市长要求您为建造东方展览馆寻找地方,您必须找到使从所有房屋到展览馆的总距离最小的位置的数量(带有整数坐标的点)。展览馆可以建在与房屋相同的地方,两点(x1,y1)和(x2,y2)之间的距离是| x1-x2 | + | y1-y2 |,其中| x |是x的绝对值。
思路
本题实际为中位数的二维推广,一维状态下若数量为奇数,则展览馆位置唯一(第(n+1)/2个数)。若为偶数,则可以在第n/2与第n/2+1之间任意选取,二维状态下只需要将符合条件的矩阵面积求出即可。
注意:端点是可以选取的
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+5;
typedef long long ll;
const int inf=1e9;
ll x[maxn],y[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>x[i]>>y[i];
if(n%2)
cout<<"1"<<endl;
else
{
sort(x+1,x+1+n);
sort(y+1,y+1+n);
cout<<(x[n/2+1]-x[n/2]+1)*(y[n/2+1]-y[n/2]+1)<<endl;
}
}
return 0;
}
C. Guessing the Greatest
有一个由n个不同数字组成的数组,在一次查询中,您可以询问子段a [l…r]中区间第二大值所在的位置。在不超过20个查询中找到数组中最大值的位置,子段a [l…r]是al,al + 1,…,ar中的所有值。询问此子段后,您将获得整个数组中该子段第二大值的位置。
思路
之前比赛里接触过二分交互题,本题与之类似,对于1e5的数据量,log的复杂度显然是符合要求的。由于每次问询获得的结果为区间的第二大值的位置,所以我们可以将整个区间中第二大值的位置ans作为二分的依据。如果在ans为端点的某段区间内,区间第二大值的位置不等于ans,则说明最大值不在此区间中。所以在获得ans后即可初步确定区间最大值所在的区间范围,然后根据mid与ans所组成的区间的区间第二大值位置是否等于ans来确定最大值位于哪一区间。
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+5;
typedef long long ll;
const int inf=1e9;
int ans,tmp;
int ask(int l,int r)
{
if(l==r)
return -1;//l==r的区间是不符合条件的,不可以进行问询
cout<<"? "<<l<<" "<<r<<endl;
int res;
cin>>res;
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n;
cin>>n;
int l,r;
ans=ask(1,n);
if(ask(ans,n)==ans)
{
l=ans,r=n;//最大值在ans右边的区间内
while(l<=r)
{
int mid=(l+r)/2;
if(ask(ans,mid)==ans)
r=mid-1;
else
l=mid+1;//不明白的可以画图
}
cout<<"! "<<l<<endl;
}
else
{
l=1,r=ans;
while(l<=r)
{
int mid=(l+r)/2;
if(ask(mid,ans)==ans)
l=mid+1;
else
r=mid-1;
}
cout<<"! "<<r<<endl;
}
return 0;
}