[Codeforces Round #310 DIV1D (CF555D)] Case of a Top Secret

题意

n 个钉子在墙上成一排排开,给出坐标,每次询问在某个钉子下面挂长度为l的绳子开始逆时针旋转,最后会一直绕着哪个钉子旋转。

题解

首先模拟绳子先会碰到哪颗钉子,然后转到上面,这一步非常重要,因为这之后就能保证绳子不会绕到更远的地方去。再然后就是不断地二分,模拟。

代码

/// 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值