zoukankan      html  css  js  c++  java
  • [51nod] 1467 旋转绳

    1467 旋转绳

    题目来源: CodeForces 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 80 难度:5级算法题

    平面上有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
    System Message (题目提供者)
     
    C++的运行时限为:1500 ms ,空间限制为:131072 KB 示例及语言说明请按这里
     
    Analysis分析
    模拟+二分优化
    显然,如果绳端在这个时候没法接触到某一个钉子,当它绕回去再绕回来以后,仍然没法接触到那根钉子
    二分的范围是前缀和,两个方向要分开计算
    既然是前缀和,那么在计算的时候需要将绳子也模拟成前缀和的形式,即剩余绳长 + 钉子所对应前缀和
    然后看是不是可以在两个钉子上多绕几圈(即取模)
    第一个坑点:钉子编号不按坐标增序(然而对钉子坐标是要排序的)
    第二个坑点:当两边边界的钉子都是近乎无限远的时候,需要判断是否可以在非边界钉子上快速绕圈(比如第七个点)
    (当然这可能只卡我的写法)
    第三个...坑点:记得 stdio.h
     
    Code代码
      1 #include<stdio.h>
      2 #include<algorithm>
      3 #include<iostream>
      4 using namespace std;
      5 
      6 long long trans[1000000],LtoR[1000000],RtoL[1000000];
      7 int n,m;
      8 int Time = 0;
      9 
     10 struct data{
     11     long long val,ord;
     12 }arr[1000000];
     13 
     14 bool cmp(const data &a,const data &b){
     15     return a.val < b.val;
     16 }
     17 
     18 int L_find(long long x){
     19     int L = 1,R = n,mid;
     20     while(L < R){
     21         mid = (L+R+1)/2;
     22         if(LtoR[mid] <= x) L = mid;
     23         else R = mid-1;
     24     }return L;
     25 }
     26 
     27 int R_find(long long x){
     28     int L = 1,R = n,mid;
     29     while(L < R){
     30         mid = (L+R)/2;
     31         if(RtoL[mid] <= x) R = mid;
     32         else L = mid+1;    
     33     }return L;
     34 }
     35 
     36 int rotate_toR(int &pos,long long &L){
     37     L += LtoR[pos];
     38     int tar = L_find(L);
     39     if(pos != 1 && arr[tar].val-arr[pos-1].val > L-LtoR[tar] && arr[tar].val-arr[pos].val)
     40         L = (L-LtoR[tar])%(2*(arr[tar].val-arr[pos].val))+LtoR[tar];
     41     L -= LtoR[tar];
     42 //    printf("CheckPoint A: tar%d L%d
    ",tar,L);
     43     if(LtoR[tar] && L > LtoR[tar]*2) L %= LtoR[tar]*2;
     44 //    printf("CheckPoint AA: tar%d L%d
    ",tar,L);
     45 //    if(!L){ pos = tar; return 1; }
     46     pos = tar;
     47     return 1; // Then keep dir
     48 }
     49 
     50 int rotate_toL(int &pos,long long &L){
     51     L += RtoL[pos];
     52     int tar = R_find(L);
     53     if(pos != n && arr[pos+1].val-arr[tar].val > L-RtoL[tar] && arr[pos].val-arr[tar].val)
     54         L = (L-RtoL[tar])%(2*(arr[pos].val-arr[tar].val))+RtoL[tar];
     55     L -= RtoL[tar];
     56     if(RtoL[tar] && L > RtoL[tar]*2) L %= RtoL[tar]*2;
     57 //    printf("CheckPoint B: tar%d L%d
    ",tar,L);
     58 //    if(!L){ pos = tar; return 1; }
     59     pos = tar;
     60     return 0; // Then keep dir
     61 }
     62 
     63 long long readll(){
     64     long long ret = 0; char ctr = getchar();
     65     while(ctr < '0' || ctr > '9') ctr = getchar();
     66     while(ctr >= '0' && ctr <= '9') ret = ret*10+ctr-'0',ctr = getchar();
     67     return ret;
     68 }
     69 
     70 int read(){
     71     int ret = 0; char ctr = getchar();
     72     while(ctr < '0' || ctr > '9') ctr = getchar();
     73     while(ctr >= '0' && ctr <= '9') ret = ret*10+ctr-'0',ctr = getchar();
     74     return ret;
     75 }
     76 
     77 int main(){
     78     scanf("%d%d",&n,&m);
     79 //    n = read(),m = read();
     80         
     81     for(int i = 1;i <= n;i++){
     82         scanf("%lld",&arr[i].val);
     83 //        arr[i].val = readll();
     84         arr[i].ord = i;
     85     }
     86 
     87     sort(arr+1,arr+1+n,cmp);
     88     
     89     for(int i = 1;i <= n;i++)
     90         trans[arr[i].ord] = i;
     91     
     92     LtoR[1] = 0;
     93     for(int i = 2;i <= n;i++)
     94         LtoR[i] = LtoR[i-1]+arr[i].val-arr[i-1].val;
     95     RtoL[n] = 0;
     96     for(int i = n-1;i >= 1;i--)
     97         RtoL[i] = RtoL[i+1]+arr[i+1].val-arr[i].val;
     98     
     99 //    for(int i = 1;i <= n;i++) printf("%d ",LtoR[i]); cout << endl;
    100     
    101     while(m--){
    102         int pos = 0; long long L = 0;
    103         scanf("%d%lld",&pos,&L);
    104 //        pos = read(), L = readll();
    105         
    106         pos = trans[pos];
    107         
    108         int times = 0,dir = 0;
    109         while(times < 2){
    110             int last = pos;
    111 //            cout << "CTime: " << Time++ << " Pos " << pos << " L " << L << endl;
    112             if(!dir) dir = rotate_toR(pos,L);
    113             else dir = rotate_toL(pos,L);
    114             
    115             if((pos+1 > n || L < arr[pos+1].val-arr[pos].val) && (pos-1 < 1 || L < arr[pos].val-arr[pos-1].val)) times = 2; 
    116             
    117 //            if(pos == last) times++;
    118 //            else times = 0;
    119 //            cout << "Time: " << Time++ << endl;
    120         }printf("%d
    ",arr[pos].ord);
    121     }
    122     
    123     return 0;
    124 }
    qwq 一个补丁打了一晚上
  • 相关阅读:
    NSLocalizedString用法
    4-27学习心得
    手势学习
    plist处理
    数据存储
    initWithFrame方法
    控制器跳转小常识
    UIGestureRecognizer学习笔记
    博客资源
    检测手机wifi有没有打开
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7689343.html
Copyright © 2011-2022 走看看