JZOJ3101. NOIP2012提高组 开车旅行
来源:互联网 发布:网络编程难吗 编辑:程序博客网 时间:2024/05/02 02:30
题目大意
给定
A和B轮流开车,只能从编号小的到编号大的。每次A会从当前这一位置开到第二近的下一位置,B会从当前开到最近的下一位置。
当他们行驶的总路程超过
现在有两个问题。
- 给定一个
X ,询问从哪个点出发,最终A走的路程与B路程的比值最小。 - 给
m 个询问,每个询问要求从给定起点Si 出发,不超过Xi 是,AB分别行驶的路程。
Data Constraint
题解
因为我们需要尽可能逼近最终停下的位置,所以可以考虑倍增。
设
然后用set预处理出每个位置AB分别会怎么走。这样一来
对于第一个问题,枚举起点然后倍增。
第二个问题就直接倍增。
时间复杂度:
SRC
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#include<set>using namespace std ;#define N 100000 + 10typedef long long ll ;const int inf = 0x7FFFFFFF ;const int MAXN = 18 ;struct Note { int v , h ; Note ( int V = 0 , int H = 0 ) { v = V , h = H ; }} ;bool operator < ( Note a , Note b ) { return ( a.v < b.v || ( a.v == b.v && a.h < b.h ) ) ; }bool operator == ( Note a , Note b ) { return a.v == b.v && a.h == b.h ; }set < Note > Q ;int H[N] , NextA[N] , NextB[N] ;ll f[N][MAXN] , g[N][MAXN] , Next[N][MAXN] ;int n , m , X0 , wz , del ;long double q , ans = 1e15 ;ll dis1 , dis2 ;long double fabs( long double x ) { return x < 0 ? -x : x ; }bool cmp( Note a , Note b ) { if ( a.h == -inf || a.h == inf || a.h == -inf + 1 || a.h == inf - 1 ) return 0 ; if ( b.h == inf || b.h == -inf || b.h == -inf + 1 || b.h == inf - 1 ) return 1 ; if ( a.v < b.v ) return 1 ; if ( a.v == b.v && a.h < b.h ) return 1 ; return 0 ;}Note Smin( Note a , Note b ) { if ( cmp( Note( abs(a.v-del) , a.v ) , Note( abs(b.v-del) , b.v ) ) ) return a ; return b ;}void Pre() { Q.insert( Note( inf , 0 ) ) , Q.insert( Note( -inf , 0 ) ) ; Q.insert( Note( inf - 1 , 0 ) ) , Q.insert( Note( -inf + 1 , 0 ) ) ; for (int i = n ; i >= 1 ; i -- ) { del = H[i] ; set < Note > :: iterator it = Q.upper_bound( H[i] ) ; Note a = *it ; it ++ ; Note b = *it ; it -- ; it -- ; Note c = *it ; it -- ; Note d = *it ; Note miN = Smin( Smin(a,b) , Smin(c,d) ) ; if ( miN == a ) a = Note( inf , 0 ) ; if ( miN == b ) b = Note( inf , 0 ) ; if ( miN == c ) c = Note( inf , 0 ) ; if ( miN == d ) d = Note( inf , 0 ) ; NextB[i] = miN.h ; miN = Smin( Smin(a,b) , Smin(c,d) ) ; NextA[i] = miN.h ; Q.insert( Note( H[i] , i ) ) ; } for (int i = 1 ; i <= n ; i ++ ) Next[i][0] = NextB[NextA[i]] , f[i][0] = abs( H[i] - H[NextA[i]] ) , g[i][0] = abs( H[NextA[i]] - H[NextB[NextA[i]]] ) ; for (int j = 1 ; j < MAXN ; j ++ ) { for (int i = 1 ; i <= n ; i ++ ) { Next[i][j] = Next[Next[i][j-1]][j-1] ; f[i][j] = f[i][j-1] + f[Next[i][j-1]][j-1] ; g[i][j] = g[i][j-1] + g[Next[i][j-1]][j-1] ; } }}void Find( int st , int lim ) { dis1 = 0 , dis2 = 0 ; for (int i = MAXN - 1 ; i >= 0 ; i -- ) { if ( f[st][i] + g[st][i] + dis1 + dis2 <= lim ) { dis1 += f[st][i] ; dis2 += g[st][i] ; st = Next[st][i] ; } } if ( f[st][0] + dis1 + dis2 <= lim ) dis1 += f[st][0] ; if ( dis2 == 0 ) q = 1e14 ; else q = (long double)dis1 / dis2 ;}int main() { scanf( "%d" , &n ) ; for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &H[i] ) ; H[0] = inf ; Pre() ; scanf( "%d" , &X0 ) ; for (int i = 1 ; i <= n ; i ++ ) { Find( i , X0 ) ; if ( q < ans ) { ans = q ; wz = i ; } else if ( H[i] > H[wz] && fabs(ans - q) <= 1e-8 ) wz = i ; } printf( "%d\n" , wz ) ; scanf( "%d" , &m ) ; for (int i = 1 ; i <= m ; i ++ ) { int st , X ; scanf( "%d%d" , &st , &X ) ; Find( st , X ) ; printf( "%lld %lld\n" , dis1 , dis2 ) ; } return 0 ;}
以上.
1 0
- JZOJ3101. NOIP2012提高组 开车旅行
- 【jzoj3101】【NOIP2012提高组】【开车旅行】
- 【NOIP2012提高组】开车旅行
- 【NOIP2012提高组】开车旅行
- 【NOIP2012提高组】开车旅行
- JZOJ 3101【NOIP2012提高组】开车旅行
- 【开车旅行】题解(NOIP2012提高组)
- NOIP2012提高组 开车旅行 题解+代码
- NOIP2012提高组 开车旅行 解题报告
- NOIP2012提高组 开车旅行 题解
- 【NOIP2012提高组D2T3】【洛谷P1081】开车旅行
- 【NOIP2012】开车旅行
- NOIP2012 开车旅行 (倍增)
- NOIP2012 开车旅行
- NOIP2012 D1T3 开车旅行
- 【NOIP2012】Day1T3 开车旅行
- NOIP2012 开车旅行
- NOIP2012开车旅行
- 动态和静态链接库总结
- TCMalloc的使用与源码剖析之十--------TCMalloc与APR,ptmalloc的分析比较
- AsyncTask 与Handler+Thread
- DisplayUtils
- python爬虫改进
- JZOJ3101. NOIP2012提高组 开车旅行
- RecyclerView的使用
- Ubuntu和ROS一起愉快玩耍
- Qt&Xcode 8 ERROR:Xcode not set up properly ... by running /usr/bin/xcodebuild.
- php 7 windows redis 扩展
- 文字倒序C++实现
- 修改文件编码的方法
- js ifarme中子页面为父页面添加选中时的高亮效果
- 数组指针与指针数组的知识点总结