lj的锁
lj的锁
Lj花很大力气设计了一个锁,有一天,lj用这个锁把lbn锁在了一个小房间里,准备把lbn啊掉,现在lbn要逃出这个房间,他需要解开这个锁。在平面上有n个钉子,第i个钉子的位置是(x[i],0),你需要回答m个问题,每个问题都是如下格式的:如果在第a[i]个钉子上挂一条长为l[i],末端有一个重锤的轻绳,并让它沿逆时针方向做圆周运动,显然由于大量钉子的存在,绳子会绕在一些钉子上并最终围绕其中一个钉子做圆周运动,求最后绳子做圆周运动的圆心是哪颗钉子。然而lj还有2s就要抓到lbn了,lbn为了逃命不得不求助于你,让你帮他解决那些数不清的询问。第一行两个整数n,m(1<=n,m<=2*10^5),代表钉子的个数和询问的个数。第二行n个整数x[1],x[2],…,xn,代表钉子的横坐标,保证坐标各不相同。接下来m行,每行两个整数a[i],li,代表一个询问中绳子最初挂在的钉子编号以及绳子的长度
这道题二分即可。。二分真是奥妙重重。
#include <cctype>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL maxn=2e5+5;
LL n, m;
struct node{
LL data, id;
}ar[maxn];
LL wentto[maxn], where[maxn], x[maxn], maxl, minr;
bool operator <(const node a, const node b){
return a.data<b.data;
}
inline LL getLL() {
register char ch;
register bool neg=false;
while(!isdigit(ch=getchar())) if(ch=='-') neg=true;
register LL x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return neg?-x:x;
}
int main(){
scanf("%lld%lld", &n, &m);
for (LL i=0; i<n; ++i){
ar[i].data=getLL();
ar[i].id=i;
}
sort(ar, ar+n);
for (LL i=0; i<n; ++i){
wentto[ar[i].id]=i;
where[i]=ar[i].id;
x[i]=ar[i].data;
}
LL a, lpos, rpos, dis;
LL l;
for (LL i=0; i<m; ++i){
a=getLL(), l=getLL();
a=wentto[a-1];
//lrpos存下标.lpos查大于等于它的,rpos小于等于它的
maxl=0, minr=n;
rpos=lower_bound(x, x+n, l+x[a])-x;
if (rpos+1<minr) minr=rpos+1;
if (x[rpos]!=l+x[a]) --rpos;
lpos=lower_bound(x, x+n, x[a]-l)-x;
while (lpos<rpos){
l-=x[rpos]-x[a];
a=rpos;
lpos=lower_bound(x+maxl, x+minr, x[a]-l)-x;
if (lpos>maxl) maxl=lpos;
l-=x[a]-x[lpos];
a=lpos;
rpos=lower_bound(x+maxl, x+minr, l+x[a])-x;
if (x[rpos]!=l+x[a]) --rpos;
dis=x[rpos]-x[lpos];
if (dis) l=l%(dis*2);
rpos=lower_bound(x+maxl, x+minr, l+x[a])-x;
if (x[rpos]!=l+x[a]) --rpos;
if (rpos+1<minr) minr=rpos+1;
}
printf("%lld\n", where[a]+1);
}
return 0;
}