平面上有n个钉子,他们从1到n编号,第i个钉子的坐标是 (xi, 0)。然后我们我们把一个长度为L,带重物的绳子系到第i个钉子上(那么重物所在的坐标是(xi, -L))。然后用力将重物向右推,开始逆时针旋转。同时,如果旋转的过程中碰到其它的钉子,就会绕着那个钉子旋转。假设每个钉子都很细,重物绕着它旋转时,不影响到绳子的长度。
更一般的,如果绳子碰到多个钉子,那么它会绕着最远的那个钉子转。特殊的,如果绳子的末端碰到了一个钉子,那么也会绕着那个钉子以长度为0的绳子在转。
经过一段时间之后,重物就会一直绕着某个钉子转。
现在有m个查询,每个查询给出初始的绳子长度以及挂在哪个钉子下旋转,请找出重物最终会绕哪个钉子旋转。
样例解释:
Input
单组测试数据。
第一行包含两个整数n 和 m (1 ≤ n, m ≤ 2*10^5),表示钉子的数目以及查询的数目。
接下来一行包含n个整数 x1, x2, ..., xn ( -10^9 ≤ xi ≤ 10^9),表示每个钉子的坐标。保证输入的钉子的坐标两两不相同。
接下来m行给出查询。每行给出ai (1 ≤ ai ≤ n) 和 li(1 ≤ li ≤ 10^9),表示该查询的重物挂在第ai个钉子上,绳子长度是li。
Output
输出m行,第i行输出第i个查询的重物最终绕着哪个钉子转。
Input示例
3 2
0 3 5
2 3
1 8
Output示例
3
2
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
struct Node
{
int index;
int pos;
};
bool cmp(const Node &a, const Node &b)
{
return a.pos < b.pos;
}
const int MAXN = 2e5 + 10;
int n, m;
int x[MAXN];
Node y[MAXN];
int flag = 0;
template <class T>
inline bool scan_d(T &ret)
{
char c;
int sgn;
if (c = getchar(), c == EOF)
{
return 0; //EOF
}
while (c != '-' && (c < '0' || c > '9'))
{
c = getchar();
}
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9')
{
ret = ret * 10 + (c - '0');
}
ret *= sgn;
return 1;
}
template <class T>
inline void out_d(T a)
{ // 输出外挂
if (a < 0)
{
putchar('-');
a = -a;
}
if (a >= 10)
{
out_d(a / 10);
}
putchar(a % 10 + '0');
}
int findStart(int pos)
{
int left = 1;
int right = n;
while (left < right)
{
int mid = left + (right - left) / 2;
if (y[mid].pos == pos)
{
return mid;
}
else if (y[mid].pos < pos)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
return -1;
}
bool bs(int &start, int &index, int &pos, int &len)
{
if (start == n || len == 0)
{
return true;
}
int left = start + 1;
int right = n;
while (left < right - 1)
{
int mid = left + (right - left) / 2;
if (y[mid].pos - pos == len)
{
start = mid;
index = y[mid].index;
pos = y[mid].pos;
len = 0;
return true;
}
else if (y[mid].pos - pos < len)
{
left = mid;
}
else
{
right = mid;
}
}
if (y[right].pos - pos <= len)
{
start = right;
index = y[right].index;
len -= (y[right].pos - pos);
pos = y[right].pos;
if (y[right].pos - pos < len)
{
return false;
}
}
else if (y[left].pos - pos <= len)
{
start = left;
index = y[left].index;
len -= (y[left].pos - pos);
pos = y[left].pos;
if (y[left].pos - pos < len)
{
return false;
}
}
return true;
}
bool bs2(int &start, int &index, int &pos, int &len)
{
if (start == 1 || len == 0)
{
return true;
}
int left = 1;
int right = start - 1;
while (left < right - 1)
{
int mid = left + (right - left) / 2;
if (pos - y[mid].pos == len)
{
start = mid;
index = y[mid].index;
pos = y[mid].pos;
len = 0;
return true;
}
else if (pos - y[mid].pos < len)
{
right = mid;
}
else
{
left = mid;
}
}
if (pos - y[left].pos <= len)
{
start = left;
index = y[left].index;
len -= (pos - y[left].pos);
pos = y[left].pos;
if (pos - y[left].pos < len)
{
return false;
}
}
else if (pos - y[right].pos <= len)
{
start = right;
index = y[right].index;
len -= (pos - y[right].pos);
pos = y[right].pos;
if (pos - y[right].pos < len)
{
return false;
}
}
return true;
}
void solve(int &start, int &index, int &pos, int &len)
{
bool result = false;
bool result2 = false;
int temp = 0;
while (true)
{
if (!flag)
{
result = bs(start, index, pos, len);
}
else
{
temp = start;
result2 = bs2(start, index, pos, len);
if (temp == start + 1)
{
int dis = y[temp].pos - y[start].pos;
if ((len / dis) & 1)
{
index = y[temp].index;
}
else
{
index = y[start].index;
}
break;
}
}
if (result && result2)
{
break;
}
flag ^= 1;
}
}
int main()
{
scan_d(n);
scan_d(m);
for (int i = 1; i <= n; i++)
{
scan_d(x[i]);
y[i].index = i;
y[i].pos = x[i];
}
sort(y + 1, y + n + 1, cmp);
int index, len;
for (int i = 0; i < m; i++)
{
scan_d(index);
scan_d(len);
int start = findStart(x[index]);
flag = 0;
int pos = x[index];
solve(start, index, pos, len);
out_d(index);
putchar(10);
}
return 0;
}