题意
n
个钉子在墙上成一排排开,给出坐标,每次询问在某个钉子下面挂长度为
题解
首先模拟绳子先会碰到哪颗钉子,然后转到上面,这一步非常重要,因为这之后就能保证绳子不会绕到更远的地方去。再然后就是不断地二分,模拟。
代码
/// by ztx
#include <cstdio>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
typedef long long ll ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
if (CH == '-') NEG = true , CH = getchar() ;
while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
if (NEG) ret = -ret ;
}
#include <algorithm>
#define maxn 200010LL
#define infi 2000000001LL
#define down 1
#define up -1
int n, data[maxn], id[maxn], rank[maxn], val[maxn];
inline bool cmp(const int&a,const int&b) { return data[a] < data[b]; }
int main() {
int m, i, p, q, l, d, r;
bool unord;
read(n), read(m);
unord = false, data[0] = -infi;
Rep (i,1,n) if (read(data[i]), id[i] = i, data[i-1] > data[i]) unord = true;
if (unord) std::sort(id+1,id+n+1,cmp);
Rep (i,1,n) rank[id[i]] = i, val[i] = data[id[i]];
val[n+1] = infi;
while (m --> 0) {
read(p), read(l), p = rank[p];
q = std::upper_bound(val,val+n+2,val[p]+l)-val-1;
l -= val[q]-val[p], p = q, d = up;
while (true) {
if (d == down) q = std::upper_bound(val+1,val+n+2,val[p]+l*d)-val-1;
else q = std::lower_bound(val+1,val+n+2,val[p]+l*d)-val;
if (p == q) break;
if (r = std::abs(val[p]-val[q]), (l/r)&1) p = q, d = -d;
l %= r;
}
printf("%d\n", id[p]);
}
getchar(),getchar();
return 0;
}