1. 程式人生 > >[51nod] 1467 旋轉繩

[51nod] 1467 旋轉繩

第一個 回來 tro 優化 ctr code long data can

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\n",tar,L);
 43     if(LtoR[tar] && L > LtoR[tar]*2) L %= LtoR[tar]*2;
 44 //    printf("CheckPoint AA: tar%d L%d\n",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\n",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\n",arr[pos].ord);
121     }
122     
123     return 0;
124 }
qwq 一個補丁打了一晚上

[51nod] 1467 旋轉繩