题意:两人轮流开车,求解一些问题(题目已经讲得很清楚了)
题解:
- 首先预处理出每座城市的最近点和次近点(可以用双向链表做,排序后从左到右依次找,找了之后就删掉)
- 然后预处理倍增,注意这时的城市已经是排序过后的了,可以转化成原来的排列进行操作也可以直接在新排列上进行。
- 接下来模拟就好咯
具体看代码,这次写的有点复杂其实是因为我不会指针再加上作死
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN = 100001;
const double INF = 2147483647;
struct Node{
int Height, Num;
int Pre, Nxt;
int Next[2];
}City[MAXN];
int N, M, x0, Head[MAXN];
int Dis_A[MAXN][20], Dis_B[MAXN][20], City_Jumper[MAXN][20];
inline int read(){
int k = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
return k * f;
}
inline void Build_Link(){
for(int i = 1; i <= N; i++){
City[i].Pre = i - 1, City[i].Nxt = i + 1;
Head[City[i].Num] = i;
}
City[1].Pre = City[N].Nxt = 0;
for(int i = 1; i <= N; i++){
int Cur = Head[i]; //从左到右的城市
if(City[Cur].Pre){
Cur = City[Cur].Pre; //前一个
City[Head[i]].Next[0] = Cur;
if(City[Cur].Pre){
Cur = City[Cur].Pre; //再前一个
if(City[Head[i]].Height - City[Cur].Height <
abs(City[Head[i]].Height - City[City[Head[i]].Next[0]].Height)){
City[Head[i]].Next[1] = City[Head[i]].Next[0];
City[Head[i]].Next[0] = Cur;
}
else{
City[Head[i]].Next[1] = Cur;
}
}
}
Cur = Head[i];
if(City[Cur].Nxt){
Cur = City[Cur].Nxt; //后一个
if(City[Cur].Height - City[Head[i]].Height <
abs(City[Head[i]].Height - City[City[Head[i]].Next[0]].Height)
|| !City[Head[i]].Next[0]){
City[Head[i]].Next[1] = City[Head[i]].Next[0];
City[Head[i]].Next[0] = Cur;
}
else if(City[Cur].Height - City[Head[i]].Height <
abs(City[Head[i]].Height - City[City[Head[i]].Next[1]].Height)
|| !City[Head[i]].Next[1]){
City[Head[i]].Next[1] = Cur;
}
if(City[Cur].Nxt){
Cur = City[Cur].Nxt; //再后一个
if(City[Cur].Height - City[Head[i]].Height <
abs(City[Head[i]].Height - City[City[Head[i]].Next[0]].Height)){
City[Head[i]].Next[1] = City[Head[i]].Next[0];
City[Head[i]].Next[0] = Cur;
}
else if(City[Cur].Height - City[Head[i]].Height <
abs(City[Head[i]].Height - City[City[Head[i]].Next[1]].Height)
|| !City[Head[i]].Next[1]){
City[Head[i]].Next[1] = Cur;
}
}
}
City[City[Head[i]].Pre].Nxt = City[Head[i]].Nxt;
City[City[Head[i]].Nxt].Pre = City[Head[i]].Pre;
}
return;
}
void Build_Multiply(){
for(int i = 1; i <= N; i++){
City_Jumper[i][0] = City[City[i].Next[1]].Next[0];
if(City[i].Next[0]){
Dis_A[i][0] = abs(City[City[i].Next[1]].Height - City[i].Height);
}
if(City_Jumper[i][0]){
Dis_B[i][0] = abs(City[City_Jumper[i][0]].Height -
City[City[i].Next[1]].Height);
}
}
for(int j = 1; j <= 18; j++){
for(int i = 1; i <= N; i++){
City_Jumper[i][j] = City_Jumper[City_Jumper[i][j - 1]][j - 1];
Dis_A[i][j] = Dis_A[i][j - 1] + Dis_A[City_Jumper[i][j - 1]][j - 1];
Dis_B[i][j] = Dis_B[i][j - 1] + Dis_B[City_Jumper[i][j - 1]][j - 1];
}
}
return;
}
int Solve_Problem_1(){
long long DisA_Already, DisB_Already;
int Cur, Ans_City = 0;
double Ans_Val = INF;
for(int i = 1; i <= N; i++){
Cur = Head[i]; DisA_Already = DisB_Already = 0;
for(int j = 18; j >= 0; j--){
if(City_Jumper[Cur][j]
&& DisA_Already + DisB_Already + Dis_A[Cur][j] + Dis_B[Cur][j] <= x0){
DisA_Already += Dis_A[Cur][j];
DisB_Already += Dis_B[Cur][j];
Cur = City_Jumper[Cur][j];
}
}
if(City[Cur].Next[1]
&& DisA_Already + DisB_Already + Dis_A[Cur][0] <= x0){
DisA_Already += Dis_A[Cur][0];
}
// printf("%d %lf\n", Head[i], (double)DisA_Already / DisB_Already);
if(DisB_Already && Ans_Val > (double)DisA_Already / DisB_Already){
Ans_Val = (double)DisA_Already / DisB_Already;
Ans_City = i;
}
}
return Ans_City;
}
void Solve_Problem_2(int x0, int Cur){
long long DisA_Already = 0, DisB_Already = 0;
for(int j = 18; j >= 0; j--){
if(City_Jumper[Cur][j]
&& DisA_Already + DisB_Already + Dis_A[Cur][j] + Dis_B[Cur][j] <= x0){
DisA_Already += Dis_A[Cur][j];
DisB_Already += Dis_B[Cur][j];
Cur = City_Jumper[Cur][j];
}
}
if(City[Cur].Next[1] && DisA_Already + DisB_Already + Dis_A[Cur][0] <= x0){
DisA_Already += Dis_A[Cur][0];
}
printf("%lld %lld\n", DisA_Already, DisB_Already);
return;
}
inline bool cmp(Node a, Node b){
return a.Height < b.Height;
}
int main(){
N = read();
for(int i = 1; i <= N; i++){
City[i].Height = read();
City[i].Num = i;
}
sort(City + 1, City + N + 1, cmp);
Build_Link(); Build_Multiply();
x0 = read(), M = read();
//Solve Problem 1
int Ans1 = Solve_Problem_1();
printf("%d\n", Ans1);
//Solve Problem 2
for(int i = 1; i <= M; i++){
int s = read(), x = read();
Solve_Problem_2(x, Head[s]);
}
return 0;
}