小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為hi,城市 i 和城市 j 之間的距離 d[i,j]恰好是這兩個城市海拔高度之差的絕對值,即d[i,j] = |hi− hj|。 旅行過程中,小 a 和小 b 輪流開車,第一天小 a 開車,之後每天輪換一次。他們計畫選擇乙個城市 s 作為起點,一直向東行駛,並且最多行駛 x 公里就結束旅行。小 a 和小 b的駕駛風格不同,小 b 總是沿著前進方向選擇乙個最近的城市作為目的地,而小 a 總是沿著前進方向選擇第二近的城市作為目的地(注意:本題中如果當前城市到兩個城市的距離相同,則認為離海拔低的那個城市更近)。如果其中任何一人無法按照自己的原則選擇目的城市,或者到達目的地會使行駛的總距離超出 x 公里,他們就會結束旅行。在啟程之前,小 a 想知道兩個問題:
1.對於乙個給定的 x=x0,從哪乙個城市出發,小 a 開車行駛的路程總數與小 b 行駛的路程總數的比值最小(如果小 b 的行駛路程為 0,此時的比值可視為無窮大,且兩個無窮大視為相等)。如果從多個城市出發,小 a 開車行駛的路程總數與小 b 行駛的路程總數的比值都最小,則輸出海拔最高的那個城市。
2.對任意給定的 x=xi和出發城市 si,小 a 開車行駛的路程總數以及小 b 行駛的路程總數。
先用std::set
預處理出對於每乙個位置小a會走到**,小b會走到**;然後考慮倍增,用ne
xai,
j 表示從第
i 個位置開始二人分別走2j
次,小a走的距離之和,ne
xbi,
j 同理,po
si,j
表示從i 開始走2j
次後的位置,直接處理每個詢問即可。
//author: hany01
#include
#define for(i , j , k) for (register int i = (j) , _##end_ = (k) ; i <= _##end_ ; ++ i)
#define fordown(i , j , k) for (register int i = (j) , _##end_ = (k) ; i >= _##end_ ; -- i)
#define set(a , b) memset(a , b , sizeof(a))
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define inf (0x3f3f3f3f)
#define inf1 (2139062143)
#define mod (1000000007)
using
namespace
std;
typedef
long
long ll;
template
inline
bool chkmax(t &a , t b)
template
inline
bool chkmin(t &a , t b)
int _ , __;
char c_;
inline
int read()
inline
void file()
const
int maxn = 100010;
struct item
};set
set;
typedef
set::iterator it;
struct frac
bool
operator == (const frac &a) const
};int n , h[maxn] , s[maxn] , x[maxn] , m , min1 , min2 , nexa[maxn] , nexb[maxn] , pos[maxn][18] , log2n;
ll lena[maxn][18] , lenb[maxn][18];
inline
void checkmin(int &min1 , int &min2 , int id , int now)
inline
void init()
).first , it;
if (itt != set.begin())
}if (itt != -- set.end())
nexb[i] = min1, nexa[i] = min2;
}for(i , 1 , n)
log2n = (int)ceil(log(n * 1.0) / log(2.0));
for(i , 1 , log2n) for(j , 1 , n)
}inline
void solve1()
, tmp;
h[0] = -inf;
for(i , 1 , n)
if (nexa[now] && suma + sumb + lena[now][0] <= x[0]) suma += lena[now][0];
tmp = (frac);
if (!suma && !sumb) continue;
if (!chkmin(ans , tmp) && tmp == ans && h[i] > h[ans.id]) ans = tmp;
}printf("%d\n" , ans.id);
}inline
void solve2()
if (nexa[now] && suma + sumb + lena[now][0] <= x[i]) suma += lena[now][0];
printf("%d %d\n", suma, sumb);
}}int main()
//燕台一去客心驚,笳鼓喧喧漢將營。
//萬里寒光生積雪,三邊曙色動危旌,
//沙場烽火侵胡月,海畔雲山擁薊城。
//少小雖非投筆吏,**還欲請長纓。
//--祖詠《望薊門》
NOIP2012開車旅行 倍增
小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為hi,城市 i 和城市 j 之間的距離 d i,j 恰好是這兩個城市海拔高度之差的絕對值,即d i,j hi hj 旅行過程中...
noip2012 開車旅行 set 倍增
因為要快速查詢向後跳應該是哪乙個點,所以用set,迭代器左右晃一下查詢最接近的兩個元素 p選手是不是只能用平衡樹 然後用倍增記錄i節點跳2 j步後,a和b分別走的距離。具體的細節和統計答案也需要注意。include include include include include include de...
NOIP2012 開車旅行 SET 倍增
啊,看到題 字好多。然後就直接開始碼暴力模擬了,覺得可以預處理一下每個點可以到達的最近點和次近點,這樣大概就有50分了 然而實際有70分。我忽略了只能往後走這一點帶來的便利,於是每一次都要找一次最近點 次近點 果然弱啊 暴力的過程寫的蠻。第一次只騙到15分 後來發現了bug調到35.就開始在精度這裡...