1A Stairs and Elevators
读题费了半天劲。有个大楼有 n n 层,每层有 m m 个房间,总之就是个 n∗m n ∗ m 的表格。楼里有一些电梯和楼梯。在同一楼层走的速度是 1 1 。坐楼梯上下走的速度是每单位时间最多走 v v ,走少于 v v 也要花一单位时间。爬楼梯的速度是 1 1 。问你从一个房间到另一个房间的最短时间。
如果在同一楼层那肯定直接走就行了。
不在同一楼层,那不是直接坐电梯就是直接爬楼梯,中间换电/楼梯没有意义。那电梯的话肯定选出门左走第一个或者出门右走第一个,楼梯也是一样的道理。然后就做完了。
#include
using namespace std;
const int N=100010;
const int INF=0x3f3f3f3f;
int li[N],ei[N];
int main()
{
int n,m,cl,ce,v;
scanf("%d%d%d%d%d",&n,&m,&cl,&ce,&v);
for(int i=1;i<=cl;i++)scanf("%d",li+i);li[cl+1]=m+1;
for(int i=1;i<=ce;i++)scanf("%d",ei+i);ei[ce+1]=m+1;
int q;
scanf("%d",&q);
while(q--)
{
int x1,y1,x2,y2,ans=INF;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1==x2){printf("%d\n",abs(y1-y2));continue;}
int l=0,r=cl+1;
while(l1)
{
int mid=(l+r)>>1;
if(li[mid]<=y1)l=mid;
else r=mid;
}
if(l)ans=min(ans,abs(y1-li[l])+abs(y2-li[l])+abs(x1-x2));
if(r!=cl+1)ans=min(ans,abs(y1-li[r])+abs(y2-li[r])+abs(x1-x2));
l=0,r=ce+1;
while(l1)
{
int mid=(l+r)>>1;
if(ei[mid]<=y1)l=mid;
else r=mid;
}
if(l)ans=min(ans,abs(y1-ei[l])+abs(y2-ei[l])+(abs(x1-x2)+v-1)/v);
if(r!=ce+1)ans=min(ans,abs(y1-ei[r])+abs(y2-ei[r])+(abs(x1-x2)+v-1)/v);
printf("%d\n",ans);
}
return 0;
}
1B Resource Distribution
有两个service, n n 个server,第 i i 个server的性能是 ci c i ,你可以把两个service分别等分,假设性能需求为 Si S i 的service被分成了 x x 份,那么他将需要 x x 个性能不低于 Six S i x (并不下取整)的server来process,每个server只能process一个service。问用这些server能否process这两个service,能的话输出方案。
假设用到的server中性能最低的性能是 c c ,且它process的service的性能需求是 S S ,那么该service至少要被分成 ⌈Sc⌉ ⌈ S c ⌉ 份。贪心地考虑,给这个service分配性能不低于 c c 的最差的 ⌈Sc⌉ ⌈ S c ⌉ 个server,然后剩下的server就是最好的那几个了(因为假设了用到的server中的最低性能,所以不考虑更差的那些),判断这些server能否process另一个service,这个可以前缀预处理。
所以只要 O(n) O ( n ) 枚举最低性能即可。
#include
using namespace std;
const int N=300010;
const int INF=0x3f3f3f3f;
struct server
{
int c,id;
bool operator <(const server &t)const{return cint ok1[N],ok2[N];
int main()
{
int n,x1,x2;
scanf("%d%d%d",&n,&x1,&x2);
for(int i=1;i<=n;i++)
{
scanf("%d",&sv[i].c);
sv[i].id=i;
}
sort(sv+1,sv+n+1);
for(int i=n;i;i--)
if((x1+n-i)/(n-i+1)<=sv[i].c)ok1[i]=i;
else ok1[i]=0;
for(int i=n;i;i--)ok1[i]=max(ok1[i],ok1[i+1]);
for(int i=n;i;i--)
if((x2+n-i)/(n-i+1)<=sv[i].c)ok2[i]=i;
else ok2[i]=0;
for(int i=n;i;i--)ok2[i]=max(ok2[i],ok2[i+1]);
for(int i=1;i<=n;i++)
{
int nb1=(x1+sv[i].c-1)/sv[i].c;
if(nb11){
if(ok2[i+nb1])
{
puts("Yes");
printf("%d %d\n",nb1,n-ok2[i+nb1]+1);
for(int j=i;jprintf("%d%c",sv[j].id,j==i+nb1-1?'\n':' ');
for(int j=ok2[i+nb1];j<=n;j++)printf("%d%c",sv[j].id,j==n?'\n':' ');
return 0;
}}
nb1=(x2+sv[i].c-1)/sv[i].c;
if(nb11){
if(ok1[i+nb1])
{
puts("Yes");
printf("%d %d\n",n-ok1[i+nb1]+1,nb1);
for(int j=ok1[i+nb1];j<=n;j++)printf("%d%c",sv[j].id,j==n?'\n':' ');
for(int j=i;jprintf("%d%c",sv[j].id,j==i+nb1-1?'\n':' ');
return 0;
}}
}
return 0*puts("No");
}
1C Big Secret
已知数组 b[N] b [ N ] ,求它的一个排列,使得排列的前缀异或和递增。无解输出 “No”。
贪心。一开始前缀异或和为 0 0 ,每次选择剩余数字中能使异或和变大的最小数,若当前找不到能使异或和变大的数,就输出 “No”。
正确性待证明。
#include
using namespace std;
typedef long long ll;
const int N=100010;
ll a[N];
vector b[66];
int main()
{
int n;
ll tmp;
scanf("%d",&n);
for(int i=0;iscanf("%I64d",&tmp);
for(int j=59;j>=0;j--)
if(tmp>>j&1){b[j].push_back(tmp);break;}
}
ll res=0;
for(int i=0;ifor(int j=0;j<60;j++)
if(!(res>>j&1)&&!b[j].empty())
{
a[i]=b[j].back();
b[j].pop_back();
res^=a[i];
break;
}
if(!a[i])return 0*puts("No");
}
puts("Yes");
for(int i=0;iprintf("%I64d%c",a[i],i==n-1?'\n':' ');
return 0;
}
1D Aztec Catacombs
待补
1E May Holidays
待补
1F May Holidays
待补
2A Mind the Gap
水题不表
#include
using namespace std;
typedef long long ll;
const int N=100010;
int main()
{
int n,s,lst=0;
scanf("%d%d",&n,&s);
for(int i=0;iint h,m;
scanf("%d%d",&h,&m);
int now=h*60+m;
if(lst+1+s<=now)return 0*printf("%d %d\n",lst/60,lst%60);
lst=now+1+s;
}
return 0*printf("%d %d\n",lst/60,lst%60);
}
2B Watering System
水题不表
#include
using namespace std;
const int N=100010;
const int INF=0x3f3f3f3f;
int s[100010];
int main()
{
int n,a,b;
scanf("%d%d%d",&n,&a,&b);
for(int i=0;iscanf("%d",s+i);
sort(s+1,s+n);
int sum=0;
for(int i=0;iint cnt=0;
for(int i=n-1;i;i--)
if(s[0]*a/sumelse break;
return 0*printf("%d\n",cnt);
}