[51nod] 1467 旋轉繩
阿新 • • 發佈:2017-10-19
第一個 回來 tro 優化 ctr code long data can
然後看是不是可以在兩個釘子上多繞幾圈(即取模)
第一個坑點:釘子編號不按坐標增序(然而對釘子坐標是要排序的)
第二個坑點:當兩邊邊界的釘子都是近乎無限遠的時候,需要判斷是否可以在非邊界釘子上快速繞圈(比如第七個點)
(當然這可能只卡我的寫法)
第三個...坑點:記得 stdio.h
Code代碼
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分析
模擬+二分優化
顯然,如果繩端在這個時候沒法接觸到某一個釘子,當它繞回去再繞回來以後,仍然沒法接觸到那根釘子
二分的範圍是前綴和,兩個方向要分開計算
既然是前綴和,那麽在計算的時候需要將繩子也模擬成前綴和的形式,即剩余繩長 + 釘子所對應前綴和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 旋轉繩