来源:Vijos第2次月赛,SDOI
分数:100+70+0
rank:6(似乎是…?或者低一点)
T1 包裹快递(express)
题意
有一个快递员要依次到达n个地方送包裹,每个地方有一个签收时间的区间[l[i],r[i]],必须要在时间r[i]之前(包括r[i])前送达,如果到达时间早于l[i],那么就必须等到时间l[i],送好才能走。签包裹的时间不计。
这个快递员希望车的最大速度尽可能的小,但是又要保证他的所有包裹都能送到。求这个最小的最大速度是多少。(精确到0.01)
分析
感觉就是赤裸裸的二分…每次签完就马上最大速度到后一个然后签或者等着签然后再跑…还是比较简单的。
为了方便起见,把所有的路程都乘了1000。
code
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ll long long
#define M 200005
using namespace std;
void read(ll &x){
x=0; char c=getchar();
for (; c<'0'; c=getchar());
for (; c>='0'; c=getchar())x=(x<<3)+(x<<1)+(c^'0');
}
struct AC{
ll x,y,s;
}a[M];
ll n;
bool ch(ll v){
double t=0.0;
int i;
// printf("%.2f\n",t);
for (i=1; i<=n; i++){
if (v*(a[i].y-t)<a[i].s)return 0;
t=max(1.0*a[i].x,t+1.0*a[i].s/v);
// printf("%.2f\n",t);
}
return 1;
}
int main(){
// freopen("express.in","r",stdin);
// freopen("express.out","w",stdout);
read(n);
int i;
ll l=1,r=0,res=0;
for (i=1; i<=n; i++){read(a[i].x); read(a[i].y); read(a[i].s); a[i].s*=1000ll; r+=a[i].s;}
for (; l<=r; ){
ll mid=(l+r)>>1;
// printf("\n---%.2f---\n",mid/1000.0);
if (ch(mid))res=mid,r=mid-1;
else l=mid+1;
}
printf("%.2f\n",res/1000.0);
return 0;
}
反思
虽然比赛的时候就A了不过中间查了两个错,不然估计就 爆零了…一个是读入的问题,因为读入的不是位置而是距离前一个签收点的距离然后一开始以为是距离但是样例还是过了…不过当时为了保险起见对着看了样例解释。
然后还有一个就是二分的最大值一开始直接设成最后一个距离(因为一开始看成位置然后忘了改回来了),不过好在最后也查出来了。但是这个还是觉得挺险的。
T2 逃脱(escape)
题意
有一张地图,一开始主角的位置确定(x,y),中间有n个障碍物位置分别是(xx[i],yy[i]),以及m个询问。询问(x,y)走到(qx[i],qy[i])需要操作多少次。
从一个点出发可以向四边走(没有障碍物),然后就一直朝那个方向走,直到碰到障碍物。如果走方向上没有障碍物或者出口就会一直走下去。
注意:各出口可以看做不在同一关,不会互相影响。
分析
看起来就像BFS,其实就是BFS
P70:
1<=出现的所有坐标<=1000
就可以很方便的存答案了。一开始把开始位置放进去,然后把障碍物放进去。然后每次模拟这样滑过来,滑出去了就停,碰到障碍物就加进队列然后停。对于每个点记一下从四个方向来的操作次数然后求个最小值。
p100:
首先离散一下。
对于每个x,y都记录一下在那一行(列)上的障碍物或者询问。
然后从起点出发,也是滑,从当前的位置开始向后滑,然后一碰到障碍物就停,然后将新滑出来的点离散,如果离散不了表示这个点走不了了。然后就不加队列,反之就加进去。
实现挺麻烦的…写了四个。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#define pb push_back
#define ll long long
#define pii pair<int,int>
#define A first
#define B second
#define mp make_pair
#define M 100005
using namespace std;
void read(int &x){
x=0; char c=getchar();
for (; c<'0'; c=getchar());
for (; c>='0'; c=getchar())x=(x<<3)+(x<<1)+(c^'0');
}
int n,m,xx[M],yy[M],qx[M],qy[M],mxx,mxy;
struct AAA{
int cx[4],cy[4];
void ycl(){
cx[0]=0; cx[1]=-1; cx[2]=0; cx[3]=1;
cy[0]=-1; cy[1]=0; cy[2]=1; cy[3]=0;
}
struct AC{int x,y,t;};
int dis[1005][1005][5];
bool can[1005][1005];
AC cl(int x,int y,int d,int t){
// printf("--%d--\n",d);
// printf("x:%d y:%d\n",cx[d],cy[d]);
for (; x&&y&&x<mxx&&y<mxy&&can[x][y]&&dis[x][y][d]==-1; x+=cx[d],y+=cy[d])dis[x][y][d]=t;//,printf("%d %d\n",x,y);
if (!can[x][y])return (AC){x-cx[d],y-cy[d],t};
else return (AC){0,0,-1};
}
queue<AC>q;
void solve(int x,int y){
int i,j,t;
ycl();
memset(can,1,sizeof(can));
memset(dis,-1,sizeof(dis));
for (i=1; i<=n; i++){can[xx[i]][yy[i]]=0;}
for (i=0; i<4; i++)if (dis[x][y][i]==-1&&can[x+cx[i]][y+cy[i]])q.push(cl(x,y,i,1));
for (; !q.empty(); ){
t=q.front().t; x=q.front().x; y=q.front().y; q.pop();
if (t==-1)continue;
t++;
for (i=0; i<4; i++)if (dis[x][y][i]==-1&&can[x+cx[i]][y+cy[i]])q.push(cl(x,y,i,t));
}
for (i=1; i<=m; i++){
int res=-1;
x=qx[i]; y=qy[i];
for (j=0; j<4; j++){
if (dis[x][y][j]!=-1){
if (res!=-1)res=min(res,dis[x][y][j]); else res=dis[x][y][j];
}
}
printf("%d ",res);
}
}
}p70;
struct CCC{
int sx[M<<1],sy[M<<1];
int ans[M],cntx,cnty;
vector< pii >dax[M<<1],day[M<<1];
int chx(int l,int r,int x){
int mid;
for (; l<=r; ){
mid=(l+r)>>1;
if (sx[mid]==x)return mid;
if (sx[mid]>x)r=mid-1;
else l=mid+1;
}
return 0;
}
int chy(int l,int r,int x){
int mid;
for (; l<=r; ){
mid=(l+r)>>1;
if (sy[mid]==x)return mid;
if (sy[mid]>x)r=mid-1;
else l=mid+1;
}
return 0;
}
void clx(int x){
int i,cnt=0;
sx[++cnt]=x;
for (i=1; i<=n; i++)sx[++cnt]=xx[i];
for (i=1; i<=m; i++)sx[++cnt]=qx[i];
sort(sx+1,sx+cnt+1);
cnt=unique(sx+1,sx+cnt+1)-sx-1;
for (i=1; i<=n; i++)xx[i]=chx(1,cnt,xx[i]);
for (i=1; i<=m; i++)qx[i]=chx(1,cnt,qx[i]);
cntx=cnt;
}
void cly(int y){
int i,cnt=0;
sy[++cnt]=y;
for (i=1; i<=n; i++)sy[++cnt]=yy[i];
for (i=1; i<=m; i++)sy[++cnt]=qy[i];
sort(sy+1,sy+cnt+1);
cnt=unique(sy+1,sy+cnt+1)-sy-1;
for (i=1; i<=n; i++)yy[i]=chy(1,cnt,yy[i]);
for (i=1; i<=m; i++)qy[i]=chy(1,cnt,qy[i]);
cnty=cnt;
}
struct AC{int x,y,t;};
queue<AC>q;
map< pii,bool >vis;
AC cl0(int x,int y,int t){
int i;
for (i=0; i<dax[x].size()&&dax[x][i].A<y; i++);
if (i==dax[x].size())return (AC){0,0,-1};
for (; i<dax[x].size(); i++){
if (dax[x][i].B){
if (!ans[dax[x][i].B])ans[dax[x][i].B]=t;
else ans[dax[x][i].B]=min(ans[dax[x][i].B],t);
}
else{
y=chy(1,cnty,sy[dax[x][i].A]-1);
if (!y)return (AC){0,0,-1};
return (AC){x,y,t};
}
}
return (AC){0,0,-1};
}
AC cl1(int x,int y,int t){
int i;
for (i=dax[x].size()-1; i>=0&&dax[x][i].A>y; i--);
if (i==-1)return (AC){0,0,-1};
for (; i>=0; i--){
if (dax[x][i].B){
if (!ans[dax[x][i].B])ans[dax[x][i].B]=t;
else ans[dax[x][i].B]=min(ans[dax[x][i].B],t);
}
else{
y=chy(1,cnty,sy[dax[x][i].A]+1);
if (!y)return (AC){0,0,-1};
return (AC){x,y,t};
}
}
return (AC){0,0,-1};
}
AC cl2(int x,int y,int t){
int i;
for (i=0; i<day[y].size()&&day[y][i].A<x; i++);
if (i==day[y].size())return (AC){0,0,-1};
for (; i<day[y].size(); i++){
if (day[y][i].B){
if (!ans[day[y][i].B])ans[day[y][i].B]=t;
else ans[day[y][i].B]=min(ans[day[y][i].B],t);
}
else{
x=chx(1,cntx,sx[day[y][i].A]-1);
if (!x)return (AC){0,0,-1};
return (AC){x,y,t};
}
}
return (AC){0,0,-1};
}
AC cl3(int x,int y,int t){
int i;
for (i=day[y].size()-1; i>=0&&day[y][i].A>x; i--);
if (i==-1)return (AC){0,0,-1};
for (; i>=0; i--){
if (day[y][i].B){
if (!ans[day[y][i].B])ans[day[y][i].B]=t;
else ans[day[y][i].B]=min(ans[day[y][i].B],t);
}
else{
x=chx(1,cntx,sx[day[y][i].A]+1);
if (!x)return (AC){0,0,-1};
return (AC){x,y,t};
}
}
return (AC){0,0,-1};
}
void solve(int x,int y){
int xxx=x,yyy=y;
clx(xxx); cly(yyy);
// memset(ans,-1,sizeof(ans));
xxx=x=chx(1,cntx,x); yyy=y=chy(1,cnty,y);
int i;
for (i=1; i<=n; i++)dax[xx[i]].pb(mp(yy[i],0)),day[yy[i]].pb(mp(xx[i],0));
for (i=1; i<=m; i++)dax[qx[i]].pb(mp(qy[i],i)),day[qy[i]].pb(mp(qx[i],i));
for (i=1; i<=cntx; i++)sort(dax[i].begin(),dax[i].end());
for (i=1; i<=cnty; i++)sort(day[i].begin(),day[i].end());
q.push((AC){x,y,0});
int t;
for (; !q.empty();){
t=q.front().t; x=q.front().x; y=q.front().y; q.pop();
if (vis[mp(x,y)])continue;
vis[mp(x,y)]=1;
t++;
AC nx;
nx=cl0(x,y,t); if (nx.t!=-1)q.push(nx);
nx=cl1(x,y,t); if (nx.t!=-1)q.push(nx);
nx=cl2(x,y,t); if (nx.t!=-1)q.push(nx);
nx=cl3(x,y,t); if (nx.t!=-1)q.push(nx);
}
for (i=1; i<=m; i++){
if (qx[i]==xxx&&qy[i]==yyy){printf("0 "); continue;}
if(ans[i])printf("%d ",ans[i]);
else printf("-1 ");
}
}
}p100;
int main(){
// freopen("escape.in","r",stdin);
// freopen("escape.out","w",stdout);
int xxx,yyy;
read(n); read(m); read(xxx); read(yyy);
int i;
for (i=1; i<=n; i++){read(xx[i]); read(yy[i]); mxx=max(xx[i],mxx); mxy=max(yy[i],mxy);}
for (i=1; i<=m; i++){read(qx[i]); read(qy[i]); mxx=max(qx[i],mxx); mxy=max(qy[i],mxy);}
mxx++; mxy++;
p100.solve(xxx,yyy);
return 0;
}
反思
其实 似乎在比赛的时候把正解敲出来了但是。
忘了离散初始坐标!!!突然气死。
T3 天才黑客
不会写…留坑待填。