51nod1112(xjb)

Posted ygeloutingyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1112(xjb)相关的知识,希望对你有一定的参考价值。

題目鏈接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1112

 

題意:中文題誒~

 

思路:對於函數 f(x) = a + kx,對於x足夠大的情況下,顯然f(x)的值的相對大小是只受 k 影響的.對於 n 條這樣的直線最多可以發生 (n-1)*n/2 次超越;

不過本題只要求輸出前 1e4 次超越,所以可以先二分出1e4次超越的時間點(這部分是用來優化常數的),然後再枚舉每一次超越即可.這樣的時間復雜

度爲 O(n^2),對於 1e4 的數據量只要常數小一點還是能過的...

 

代碼:

技术分享
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int MAXN = 1e4+10;
 7 const int inf = 1e4;
 8 pair<int, int> p[MAXN];//存儲開始時的數據
 9 pair<int, int> p1[MAXN];//存儲1e4時間點的數據
10 pair<double, pair<int, int> > p2[MAXN*10];//存儲答案
11 int vis[MAXN*10], n;
12 
13 int get_times(int mid){ //計算在k時間點可以達到的超越次數
14     int ans = 0;
15     for(int i=0; i<n; i++){
16         p1[i].first = p[i].first + p[i].second * mid;
17         p1[i].second = i;
18     }
19     sort(p1, p1+n);
20     for(int i=0; i<n; i++){
21         if(p1[i].second < i){
22             ans += i-p1[i].second;
23         }
24     }
25     return ans;
26 }
27 
28 void get_time(void){ //二分出達到1e4次超越的時間點
29     int l=0, r=MAXN*10;
30     int ans=0;
31     while(l < r-1){
32         int mid = (l+r)>>1;
33         int cnt = get_times(mid);
34         if(cnt == inf) break;
35         else if(cnt > inf) r = mid;
36         else l = mid;
37     }
38 }
39 
40 int main(void){
41     scanf("%d", &n);
42     for(int i=0; i<n; i++){
43         scanf("%d%d", &p[i].first, &p[i].second);
44         vis[p[i].first] = i+1;
45     }
46     sort(p, p+n);
47     get_time();
48     int indx=0;
49     for(int i=0; i<n; i++){
50         int a2 = p[p1[i].second].first;
51         for(int j=0; j<i; j++){
52             int a1 = p[p1[j].second].first;
53             if(a1 > a2){
54                 int b1 = p[p1[j].second].second;
55                 int b2 = p[p1[i].second].second;
56                 double k = (a1-a2)*1.0/(b2-b1); //本次超越的時間點
57                 p2[indx].first = k;
58                 p2[indx].second.first = vis[a2];
59                 p2[indx++].second.second = vis[a1];
60             }
61         }
62     }
63     if(!indx){
64         printf("No Solution\n");
65     }else{
66         sort(p2, p2+indx);
67         int cnt = min(indx, inf);
68         for(int i=0; i<cnt; i++){
69             printf("%d %d\n", p2[i].second.first, p2[i].second.second);
70         }
71     }
72     return 0;
73 }
View Code

 

以上是关于51nod1112(xjb)的主要内容,如果未能解决你的问题,请参考以下文章

51nod1110(xjb)

51nod1276(xjb)

51Nod 1113 矩阵快速幂

51Nod 1649 齐头并进

51nod 1442 士兵的旅行

51nod1009 数字1的数量