UVa 1468 - Restaurant(贪心 + 扫描)

题意

有A、B两个餐馆和其他餐馆,现在要建一个餐馆,使它到A或B的距离比任意一个餐馆到A或B的距离有一个短。求数目。

思路

一开始用暴力枚举,就算加了很多剪枝也TLE了TAT。

还是参考的帆神和柯神的解题报告。

要从每一列考虑。

显然在A、B两个餐馆X轴之外是不可能放置的,因为这样距离一定会比A到B或者B到A长。
所以放置地点就限制在了AB之间(X axis)

接下来考虑每一列,显然不能放在这一列离x axis 最近的餐馆的上面,因为这样一放那个最近的餐馆就两项都比他短了(X相等,Y又比他大)。

所以边读取输入边维护h[x]的最小值。

但是还有别的限制条件。

对于一个餐馆P,后一列的点K的位置必须不能同时x + 1, y + 1,也就是划上去一个格的对角线,也就是多一个高度。如果超过了这个高度,显然K到A的距离必定大于P到A的距离。(详情请参考帆神的图)

到B也一样。

所以要从前往后从后往前各扫描一遍h[x],维护min(h[x], h[x - 1](h[x + 1]) + 1)

满足了以上条件的点都可以建餐厅啦~之后就是统计了。

代码

 
 
  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. #define lowbit(x) ((x) & (-x))
  4. #define MP(a, b) make_pair(a, b)
  5. const int MAXN = 60000 + 5;
  6. const int INF = 0x3f3f3f3f;
  7. using namespace std;
  8. typedef pair<int, int> pii;
  9. typedef vector<int> vei;
  10. typedef vector<pair<int, int> >veii;
  11. typedef vector<int>::iterator viti;
  12. typedef vector<pii>::iterator vitii;
  13. typedef priority_queue<pii, vector<pii>, greater<pii> >pquii;
  14. struct POINT
  15. {
  16. int x, y;
  17. };
  18. int h[MAXN];
  19. int main()
  20. {
  21. //freopen("input.txt", "r", stdin);
  22. int T, i, j, n, len;
  23. POINT a, b;
  24. scanf("%d", &T);
  25. while (T--)
  26. {
  27. int st = INF, ed = -1;
  28. scanf("%d%d", &len, &n);
  29. scanf("%d%d%d%d", &a.x, &a.y, &b.x, &b.y);
  30. st = min(a.x, b.x), ed = max(a.x, b.x);
  31. fill(h + st + 1, h + ed, len);
  32. for (i = 3; i <= n; i++)
  33. {
  34. int x, y;
  35. scanf("%d%d", &x, &y);
  36. h[x] = min(h[x], abs(y - a.y));
  37. }
  38. h[st] = 0, h[ed] = 0;
  39. for (i = st + 1; i < ed; i++)
  40. h[i] = min(h[i], h[i - 1] + 1);
  41. for (i = ed - 1; i > st; i--)
  42. h[i] = min(h[i], h[i + 1] + 1);
  43. LL ans = 0;
  44. for (i = st + 1; i < ed; i++)
  45. {
  46. if (h[i])
  47. {
  48. ans++;
  49. ans += min(a.y, h[i] - 1);
  50. ans += min(len - a.y, h[i] - 1);
  51. }
  52. }
  53. cout << ans << endl;
  54. }
  55. return 0;
  56. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值