ACM ICPC 2015 Moscow Subregional Russia, Moscow, Dolgoprudny, October, 18, 2015 G. Garden Gathering

Problem G. Garden Gathering Input file: standard input Output file: standard output Time limit: 3 seconds Memory limit: 512 megabytes Many of you may have been to St. Petersburg, but have you visited Peterhof Palace? It is a collection of splendid palaces and gardens with spectacular fountains! Besides the beauty, it is huge, and you can easily get lost in one of the park labyrinths. Imagine that you are not a regular visitor, but one of the guides, and your group of tourists is scattered across one of the gardens — a complete disaster! To continue the tour, you need to collect them all in one place, and technologies of the XXI century could be very useful in this task. Each tourist has a smartphone with a GPS tracker which transmits data directly to your phone. Unfortunately, the application for Peterhof’s guides lacks in functionality. Actually, it has the only button which, when pressed, automatically selects one person at random and tells his or her coordinates to everyone in the group. After that, all tourists immediately start to move to this position using the shortest path, while the selected person stands still and waits for others. The only thing to worry about is that you can be late for the last train home, so you want to know the maximum possible time this gathering process could take. You have a map of this garden with you: -5 -5 -4 -4 -3 -3 -2 -2 -1 -1 0 1 1 2 2 3 3 4 4 5 5 Ox Oy Picture 1: Plan of garden trails Page 9 of 17 ACM ICPC 2015 Moscow Subregional Russia, Moscow, Dolgoprudny, October, 18, 2015 All tourists from your group travel through the park with constant speed using only the trails shown on the picture 1. If in the end you will be late, then you can ask your boss to reimburse the money spent on Yandex.Taxi. To do so, you need to present a proof in the form of two numbers: ID of the person selected by the app and ID of the person who will be the last to arrive. As you have a lot of time while the tourists are gathering, calculate any possible pair for the worst case. Input The first line of the input contains a single integer n (2 ≤ n ≤ 200 000) — the size of your group. The i-th of the next n lines contains two integers xi and yi (|xi |, |yi | ≤ 107 ) — coordinates of the tourist with ID i (numbered from 1 to n). Initial positions of all tourists are guaranteed to be distinct. Output Output ID of the selected person and ID of the last person. If there are several possible answers, output any of them. Examples standard input standard output 4 0 0 2 0 0 1 2 1 1 4 Note Picture 2: Answer for the first sample In the sample the distance between the first and the fourth tourists is √ 2 + 1. Answers (4, 1), (2, 3), and (3, 2) are also considered correct.

题意:给出方格图上N个点,点都在格点上,每个点都可以沿着上下左右,斜着四个方向,总共八个方向移动,时间花费为线的长度,问N个点到其中一个点集中,每个点都沿着最短路移动,问最后到的点最晚的时候,起点和最后到的点是哪两个点。(任意一组答案)。

分析:显然答案就是最远点对。

所以我们要求曼哈顿距离下的最远点对。

按照曼哈顿生成树的思想来做。

八个方向,根据双向性,其实每个点只用处理四个方向。而这四个方向不妨选择上面的四个方向,这样我们可以通过坐标变换用相同的方法处理。

所以我们就只用考虑一个方向,不妨考虑y=0 到 y=x 这两条直线围成的那个方向。

首先,设现在这个点为(x0, y0),要找一个这个方向上的最远点。

这个点既然在这个方向上,首先就要有x1>x0,并且y1-y0<x1-x0

然后观察时间的表达式 time = sqrt(2)*y + (x-y)

所以我们现在要求的是,对于每个点(x0, y0),找出所有的x1>x0,y1-y0<x1-x0,询问它们之中的max{time}

要保证x1>x0,我们可以将x坐标排序,然后倒序计算点即可。

要保证y1-y0<x1-x0,变形

y1-x1<y0-x0,

即找到比y0-x0小的所有yi-xi,然后找它们的max{time},这个可以用树状数组做。

 

注意的是:我觉得,以吾之拙见,上述方法可能将不是这个方向上的点算进来,

因为如果x0,y0 -> (0, 0),x1,y1 -> (2, -3)这样的话,虽然不在这个方向上,

但是x1>x0,y1-y0<x1-x0,

虽然可能算多,但是这种方法是不可能将这个方向上的点算少的。

也就是说,在这个方向上的最大值必定有被考虑到。

所以不影响答案和复杂度。

 

每个点四个方向,即上述过程要做四次,所以要O(4*nlogn)

 

  1 /**
  2 Create By yzx - stupidboy
  3 */
  4 #include <cstdio>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <cmath>
  8 #include <deque>
  9 #include <vector>
 10 #include <queue>
 11 #include <iostream>
 12 #include <algorithm>
 13 #include <map>
 14 #include <set>
 15 #include <ctime>
 16 #include <iomanip>
 17 using namespace std;
 18 typedef long long LL;
 19 typedef double DB;
 20 #define MIT (2147483647)
 21 #define INF (1000000001)
 22 #define MLL (1000000000000000001LL)
 23 #define sz(x) ((int) (x).size())
 24 #define clr(x, y) memset(x, y, sizeof(x))
 25 #define puf push_front
 26 #define pub push_back
 27 #define pof pop_front
 28 #define pob pop_back
 29 #define ft first
 30 #define sd second
 31 #define mk make_pair
 32 
 33 inline int Getint()
 34 {
 35     int Ret = 0;
 36     char Ch = ' ';
 37     bool Flag = 0;
 38     while(!(Ch >= '0' && Ch <= '9'))
 39     {
 40         if(Ch == '-') Flag ^= 1;
 41         Ch = getchar();
 42     }
 43     while(Ch >= '0' && Ch <= '9')
 44     {
 45         Ret = Ret * 10 + Ch - '0';
 46         Ch = getchar();
 47     }
 48     return Flag ? -Ret : Ret;
 49 }
 50 
 51 const int N = 200010;
 52 const DB SQRT2 = sqrt(2.0);
 53 class Point
 54 {
 55 //    private : static const double AAAAA = sqrt(234);
 56 public : 
 57     int x, y, index;
 58     inline void Read()
 59     {
 60         x = Getint();
 61         y = Getint();
 62     }
 63 
 64     inline bool operator <(const Point &a) const
 65     {
 66         if(x != a.x) return x < a.x;
 67         return y < a.y;
 68     }
 69 
 70     static DB Dist(const Point &a, const Point &b)
 71     {
 72         int dx = abs(a.x - b.x), dy = abs(a.y - b.y);
 73         if(dx < dy) swap(dx, dy);
 74         return SQRT2 * dy + (dx - dy);
 75     }
 76 
 77     inline const DB Feature()
 78     {
 79         return SQRT2 * y + (x - y);
 80     }
 81 } data[N];
 82 int n;
 83 int st, far;
 84 DB ans;
 85 class Hash
 86 {
 87 private :
 88     int arr[N], length;
 89 
 90 public :
 91     inline void Clear()
 92     {
 93         length = 0;
 94     }
 95 
 96     inline void Insert(int x)
 97     {
 98         arr[++length] = x;
 99     }
100 
101     inline void GoHash()
102     {
103         sort(arr + 1, arr + 1 + length);
104         length = unique(arr + 1, arr + 1 + length) - (arr + 1);
105         //for(int i = 1; i <= length; i++) printf("%d\n", arr[i]);
106     }
107 
108     inline int GetIndex(int x)
109     {
110         int left = 1, right = length, mid;
111         while(left <= right)
112         {
113             mid = (left + right) >> 1;
114             if(arr[mid] < x) left = mid + 1;
115             else if(arr[mid] > x) right = mid - 1;
116             else return mid;
117         }
118         return 0;
119     }
120 
121     inline int GetLength()
122     {
123         return length;
124     }
125 } ranks;
126 
127 class TreeArray
128 {
129 private :
130     DB value[N];
131     int index[N], n;
132 
133 public :
134     inline void Clear()
135     {
136         n = 0;
137     }
138 
139     inline void SetLimit(int x)
140     {
141         n = x;
142         for(int i = 1; i <= n; i++) value[i] = -1.0 * INF;
143     }
144 
145     inline int Lowbit(int x)
146     {
147         return x & (-x);
148     }
149 
150     inline void Add(Point a)
151     {
152         int x = ranks.GetIndex(a.y - a.x);
153         //printf("%d %d %d\n", a.y - a.x, x, n);
154         DB val = a.Feature();
155         for( ; x <= n; x += Lowbit(x))
156             if(val > value[x])
157                 value[x] = val, index[x] = a.index;
158     }
159 
160     inline void Query(const Point &a, DB &cnt, int &idx)
161     {
162         cnt = -1.0 * INF, idx = 0;
163         int x = ranks.GetIndex(a.y - a.x);
164         for( ; x; x -= Lowbit(x))
165             if(cnt < value[x])
166                 cnt = value[x], idx = index[x];
167     }
168 } Store;
169 
170 inline void Input()
171 {
172     n = Getint();
173     for(int i = 1; i <= n; i++)
174     {
175         data[i].Read();
176         data[i].index = i;
177     }
178 }
179 
180 inline void Solve()
181 {
182     //puts("adf");
183     ans = -1.0 * INF, st = far = 1;
184     for(int dir = 0; dir < 4; dir++)
185     {
186         //puts("asdfff");
187         if(dir == 1 || dir == 3)
188         {
189             for(int i = 1; i <= n; i++)
190                 swap(data[i].x, data[i].y);
191         }
192         else if(dir == 2)
193         {
194             for(int i = 1; i <= n; i++)
195                 data[i].x = -data[i].x;
196         }
197 
198 
199         ranks.Clear();
200         for(int i = 1; i <= n; i++)
201             ranks.Insert(data[i].y - data[i].x);
202         ranks.GoHash();
203 
204         sort(data + 1, data + 1 + n);
205         for(int i = 1; i <= n; i++)
206         Store.Clear();
207         Store.SetLimit(ranks.GetLength());
208         //puts("asdfffffx");
209         for(int i = n; i >= 1; i--)
210         {
211             //printf("%d", i);
212             DB cnt;
213             int idx;
214             Store.Query(data[i], cnt, idx);
215             //puts("xxx");
216             if(idx)
217             {
218                 cnt -= data[i].Feature();
219                 if(cnt > ans) ans = cnt, st = data[i].index, far = idx;
220             }
221             Store.Add(data[i]);
222             //puts("yyy");
223         }
224     }
225 
226     printf("%d %d\n", st, far);
227 }
228 
229 int main()
230 {
231     Input();
232     Solve();
233     return 0;
234 }
View Code

 

有人能够解答为何在类里面

private : static const double AAAAA = sqrt(234.0);

不可以吗?

转载于:https://www.cnblogs.com/StupidBoy/p/5074539.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值