C.
题目主要考察阅读理解。
对于每一组问询,答案肯定是水平走一段+电梯/楼梯走一段组合而成。之前考虑的是 有没有可能做一段电梯然后走最后一截楼梯,不过从各种别人的代码来看似乎不需要考虑这点?似乎只要对于每个问询,把离起点最近的两个电梯/楼梯都二分抓出来算一下就行了。
特别注意要特判那些两点在同一层的坑爹情况…
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,cs,ce,v,s[100005],e[100005],q,a,b,c,d,p,w,ans;
int main()
{
scanf("%d%d%d%d%d",&n,&m,&cs,&ce,&v);
for(int i=1;i<=cs;i++)
scanf("%d",&s[i]);
for(int i=1;i<=ce;i++)
scanf("%d",&e[i]);
scanf("%d",&q);
while(q--)
{
ans=1E9;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(a==c)
ans=abs(b-d);
p=lower_bound(s+1,s+cs+1,b)-s;
if(p<=cs)
ans=min(ans,abs(s[p]-b)+abs(c-a)+abs(s[p]-d));
if(p>1)
ans=min(ans,abs(s[p-1]-b)+abs(c-a)+abs(s[p-1]-d));
w=lower_bound(e+1,e+ce+1,b)-e;
if(w<=ce)
ans=min(ans,abs(e[w]-b)+(abs(c-a)-1)/v+1+abs(e[w]-d));
if(w>1)
ans=min(ans,abs(e[w-1]-b)+(abs(c-a)-1)/v+1+abs(e[w-1]-d));
printf("%d\n",ans);
}
return 0;
}
D.
题目的大意就是给你n个数和x1,x2,问能不能找到k1与k2个不同的数使得这k1个数都>=x1/k1,k2个数同理;
首先,如果能找到k=k1+k2个满足条件的数,那么我们肯定能用最大的k个数凑出来答案。于是我们枚举k,对于每个k,我们考虑如果x1使用最小的u个数,需要多少个(算u),然后考虑剩下的k-u个数是否满足x2的条件。然后调换x2与x1的地位再次计算(因为不知道x1,x2的大小关系)。可以则输出。
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,cs,ce,v,s[100005],e[100005],q,a,b,c,d,p,w,ans;
int main()
{
scanf("%d%d%d%d%d",&n,&m,&cs,&ce,&v);
for(int i=1;i<=cs;i++)
scanf("%d",&s[i]);
for(int i=1;i<=ce;i++)
scanf("%d",&e[i]);
scanf("%d",&q);
while(q--)
{
ans=1E9;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(a==c)
ans=abs(b-d);
p=lower_bound(s+1,s+cs+1,b)-s;
if(p<=cs)
ans=min(ans,abs(s[p]-b)+abs(c-a)+abs(s[p]-d));
if(p>1)
ans=min(ans,abs(s[p-1]-b)+abs(c-a)+abs(s[p-1]-d));
w=lower_bound(e+1,e+ce+1,b)-e;
if(w<=ce)
ans=min(ans,abs(e[w]-b)+(abs(c-a)-1)/v+1+abs(e[w]-d));
if(w>1)
ans=min(ans,abs(e[w-1]-b)+(abs(c-a)-1)/v+1+abs(e[w-1]-d));
printf("%d\n",ans);
}
return 0;
}