【二分】教主的花园解题报告
2012-10-15 19:56
288 查看
教主的花园
(p1.pas/cpp/in/out)
【问题背景】
LHX教主最近总困扰于前来膜拜他的人太多了,所以他给他的花园加上了一道屏障。
【问题描述】
可以把教主的花园附近区域抽像成一个正方形网格组成的网络,每个网格都对应了一个坐标(均为整数,有可能为负),若两个网格(x1, y1),(x2, y2)有|x1 – x2| + |y1 – y2| = 1,则说这两个网格是相邻的,否则不是相邻的。
教主在y = 0处整条直线上的网格设置了一道屏障,即所有坐标为(x, 0)的网格。当然,他还要解决他自己与内部人员的进出问题,这样教主设置了N个入口a1, a2, …, aN可供进出,即对于y = 0上的所有网格,只有(a1, 0),(a2, 0),……,(aN, 0) 可以通过,之外的所有纵坐标为0的网格均不能通过,而对于(x, y)有y不为0的网格可以认为是随意通过的。
现在教主想知道,给定M个点对(x1, y1),(x2, y2),并且这些点均不在屏障上,询问从一个点走到另一个点最短距离是多少,每次只能从一个格子走到相邻的格子。
【输入格式】
输入的第1行为一个正整数N,为屏障上入口的个数。
第2行有N个整数,a1, a2, …, aN,之间用空格隔开,为这N个入口的横坐标。
第3行为一个正整数M,表示了M个询问。
接下来M行,每行4个整数x1, y1, x2, y2,有y1与y2均不等于0,表示了一个询问从(x1, y1)到(x2, y2)的最短路。
【输出格式】
输出共包含m行,第i行对于第i个询问输出从(x1, y1)到(x2, y2)的最短路距离是多少。
【样例输入】
2
2 -1
2
0 1 0 -1
1 1 2 2
【样例输出】
4
2
【数据规模】
对于20%的数据,有n,m≤10,ai,xi,yi绝对值不超过100;
对于40%的数据,有n,m≤100,ai,xi,yi绝对值不超过1000;
对于60%的数据,有n,m≤1000,ai,xi,yi绝对值不超过100000;
对于100%的数据,有n,m≤100000,ai,xi,yi绝对值不超过100000000。
【考察点】
二分
【思路】
通过画图可知:所有可能的情况共3种:都在上面,都在下面,一上一下。
其中,目测可知:前两种情况可以直接横纵坐标分别相减,然后加起来即可(因为没有障碍)。后面一种稍微麻烦一点,通过画图分析:如果(x1,x2)区间上有通道,那么实际效果同前两种情况,如果没有,那么最短路一定是走最靠近(x1,x2)这个区间的某个通道。
从而问题转化成了找一个距离(x1,x2)最近的通道了,这里是坐标,很明显可以让那些通道有序,所以我们可以二分解决。
【提交情况】
1次AC
【经验】
用y1*y2<0来判断的总要中枪嘛……叫你秀高端……
【收获】
熟悉二分操作
ACCode:
(p1.pas/cpp/in/out)
【问题背景】
LHX教主最近总困扰于前来膜拜他的人太多了,所以他给他的花园加上了一道屏障。
【问题描述】
可以把教主的花园附近区域抽像成一个正方形网格组成的网络,每个网格都对应了一个坐标(均为整数,有可能为负),若两个网格(x1, y1),(x2, y2)有|x1 – x2| + |y1 – y2| = 1,则说这两个网格是相邻的,否则不是相邻的。
教主在y = 0处整条直线上的网格设置了一道屏障,即所有坐标为(x, 0)的网格。当然,他还要解决他自己与内部人员的进出问题,这样教主设置了N个入口a1, a2, …, aN可供进出,即对于y = 0上的所有网格,只有(a1, 0),(a2, 0),……,(aN, 0) 可以通过,之外的所有纵坐标为0的网格均不能通过,而对于(x, y)有y不为0的网格可以认为是随意通过的。
现在教主想知道,给定M个点对(x1, y1),(x2, y2),并且这些点均不在屏障上,询问从一个点走到另一个点最短距离是多少,每次只能从一个格子走到相邻的格子。
【输入格式】
输入的第1行为一个正整数N,为屏障上入口的个数。
第2行有N个整数,a1, a2, …, aN,之间用空格隔开,为这N个入口的横坐标。
第3行为一个正整数M,表示了M个询问。
接下来M行,每行4个整数x1, y1, x2, y2,有y1与y2均不等于0,表示了一个询问从(x1, y1)到(x2, y2)的最短路。
【输出格式】
输出共包含m行,第i行对于第i个询问输出从(x1, y1)到(x2, y2)的最短路距离是多少。
【样例输入】
2
2 -1
2
0 1 0 -1
1 1 2 2
【样例输出】
4
2
【数据规模】
对于20%的数据,有n,m≤10,ai,xi,yi绝对值不超过100;
对于40%的数据,有n,m≤100,ai,xi,yi绝对值不超过1000;
对于60%的数据,有n,m≤1000,ai,xi,yi绝对值不超过100000;
对于100%的数据,有n,m≤100000,ai,xi,yi绝对值不超过100000000。
【考察点】
二分
【思路】
通过画图可知:所有可能的情况共3种:都在上面,都在下面,一上一下。
其中,目测可知:前两种情况可以直接横纵坐标分别相减,然后加起来即可(因为没有障碍)。后面一种稍微麻烦一点,通过画图分析:如果(x1,x2)区间上有通道,那么实际效果同前两种情况,如果没有,那么最短路一定是走最靠近(x1,x2)这个区间的某个通道。
从而问题转化成了找一个距离(x1,x2)最近的通道了,这里是坐标,很明显可以让那些通道有序,所以我们可以二分解决。
【提交情况】
1次AC
【经验】
用y1*y2<0来判断的总要中枪嘛……叫你秀高端……
【收获】
熟悉二分操作
ACCode:
Program p1; Var n,m:longint; a:array[0..100010]oflongint; Procedure terminate; begin close(input); close(output); halt; end; Procedure qsort; //排序,题目没说数据有序 procedure sort(l,r: longint); var i,j,x,y:longint; begin i:=l; j:=r; x:=a[(l+r)div 2]; repeat whilea[i]<x do inc(i); whilex<a[j] do dec(j); ifnot(i>j) then begin y:=a[i]; a[i]:=a[j]; a[j]:=y; inc(i); j:=j-1; end; until i>j; if l<j then sort(l,j); if i<r then sort(i,r); end; begin sort(1,n); end; Procedure init; var i:longint; begin assign(input,'p1.in'); assign(output,'p1.out'); reset(input); rewrite(output); readln(n); for i:=1 to n do begin read(a[i]); end; a[0]:=99999999; a[n+1]:=99999999; //端点要注意,不然后面计算会把这里算上去,答案就诡异了……当然,也可以在后面特判,这种方法比较懒= = readln(m); qsort; //for i:=1 to n do //write(a[i],''); //writeln; end; Function divide(l,r,x:longint):longint; //二分查找,找一个能把X插进去的地方 var m:longint; begin whilel<r do begin m:=(l+r)>>1; if x<a[(l+r)>>1] then r:=m else l:=m+1; end; exit(m); end; Procedure main; var wjmzbmr,x1,y1,x2,y2:longint; function solve:longint; var id1,id2,min:longint; begin id1:=divide(1,n,x1); //write('id1:',id1,''); id2:=divide(1,n,x2); //记录下两个x的位置 //writeln('id2:',id2); if id1<>id2 then exit(abs(x1-x2)+abs(y1-y2)) //如果不相同,则代表a中有数位于(x1,x2)区间内 else //否则就找附近的某个最优值,其实就是左右两个点就行了……不放心可以左右多枚举几个 begin min:=$7f7f7f7f; if abs(y1-y2)+abs(x1-a[id1])+abs(x2-a[id1])<min then min:=abs(y1-y2)+abs(x1-a[id1])+abs(x2-a[id1]); //writeln('当前:',abs(y1-y2)+abs(x1-a[id1])+abs(x2-a[id1])); if abs(y1-y2)+abs(x1-a[id1+1])+abs(x2-a[id1+1])<min then min:=abs(y1-y2)+abs(x1-a[id1+1])+abs(x2-a[id1+1]); //writeln('右:',abs(y1-y2)+abs(x1-a[id1+1])+abs(x2-a[id1+1])); if abs(y1-y2)+abs(x1-a[id1-1])+abs(x2-a[id1-1])<min then min:=abs(y1-y2)+abs(x1-a[id1-1])+abs(x2-a[id1-1]); //writeln('左',abs(y1-y2)+abs(x1-a[id1-1])+abs(x2-a[id1-1])); exit(min); end; end; begin for wjmzbmr:=1 to m do begin readln(x1,y1,x2,y2); //坑爹 if(y1=0)or(y2=0) then begin writeln('欧教坑爹啊!!'); terminate; end; //输入数据不合法 //同侧 //if(y1*y2>0) then begin writeln(abs(x1-x2)+abs(y1-y2)); continue; end; If((y1<0) and (y2<0))or((y1>0)and(y2>0)) then begin writeln(abs(x1-x2)+abs(y1-y2));continue; end; //千万注意不要y1*y2,会爆Longint //不同侧 //if(y1*y2<0) then writeln(solve); if((y1>0) and (y2<0))or((y1<0)and(y2>0)) then writeln(solve); //不同侧处理 end; end; Begin init; main; terminate; End.
相关文章推荐
- BZOJ3343 教主的魔法 解题报告【数据结构】【分块】
- UVA11090 Going in Cycle!! 解题报告【判负环】【SPFA】【二分答案】
- POJ3525/LA3890 Most Distant Point from the Sea 解题报告【计算几何】【二分答案】【半平面交】
- 解题报告:HDU_2333 Assemble 二分
- Codeforces Round #211 (Div. 2) D题(二分,贪心)解题报告
- POJ 3273 Monthly Expense 解题报告(二分枚举)
- [置顶] 白话二分匹配之最大匹配+附上hdu2063解题报告
- BZOJ 1052 二分答案 解题报告
- 17.7.24 校内赛 解题报告【二分答案】【记忆化搜索】【数据结构】
- POJ-3258 River Hopscotch 解题报告(二分) 牛跳石头
- codevs 1432 总数统计 二分 解题报告
- jzoj1792 教主的花园 (二分)
- POJ 3258 River Hopscotch 解题报告(二分)
- BZOJ4952 [Wf 2017] 二分答案 解题报告
- 一中OJ #1193 倒水问题[1] | IDDFS-迭代加深 + 二分猜答案 | 解题报告
- UVAlive 3890&Poj3525 半平面交+二分 解题报告
- SDUT 2778 小明的花费预算 (二分答案) -- 解题报告
- BZOJ 4443(SCOI2015)网络流+二分答案 解题报告
- S-Tree解题报告UVa 712二叉树/二分搜索
- LuoguP2680/UOJ150[NOIP2015] 运输计划 解题报告【二分答案+树上操作(LCA)+树上差分】