[ICPC 2024 Hangzhou R] Elevator II
time limit per test
2 seconds
memory limit per test
1024 megabytes
There is a building with 109 floors but only 1 elevator. Initially, the elevator is on the f-th floor.
There are n people waiting for the elevator. The i-th person is currently on the li-th floor and wants to take the elevator to the ri-th floor (li<ri). Because the elevator is so small, it can carry at most 1 person at a time.
It costs 1 unit of electric energy to move the elevator 1 floor upwards. No energy is needed if the elevator moves downwards. That is to say, it costs max(y−x,0) units of electric energy to move the elevator from the x-th floor to the y-th floor.
Find the optimal order to take all people to their destinations so that the total electric energy cost is minimized.
More formally, let a1,a2,⋯,an be a permutation of n where ai indicates that the i-th person to take the elevator is ai. The total electric energy cost can be calculated as
∑i=1n(max(lai−ra(i−1),0)+rai−lai)
where a0=0,r0=f for convenience.
Recall that a sequence a1,a2,⋯,an of length n is a permutation of n if and only if each integer from 1 to n (both inclusive) appears exactly once in the sequence.
有道 翻译
有一栋楼有 109 层,但只有 1 部电梯。最初,电梯位于第5层。
n 人等电梯。 i 第一个人目前在 li 层,他想乘电梯到 ri 层( li<ri )。因为电梯很小,所以一次最多只能搭载一个人。
电梯 1 层向上移动需要消耗 1 单位电能。如果电梯向下移动,就不需要能量。也就是说,将电梯从 x \ 1层移动到 y \ 1层需要消耗 max(y−x,0) 个单位的电能。
找到将所有人送到目的地的最优顺序,使总电力成本最小。
更正式地说,让 a1,a2,⋯,an 是 n 的一个排列,其中 ai 表示 i \第一个乘电梯的人是 ai 。总电能成本可计算为
∑i=1n(max(lai−ra(i−1),0)+rai−lai)
为方便,其中为 a0=0,r0=f 。
回想一下,长度为 n 的序列 a1,a2,⋯,an 是 n 的排列,当且仅当从 1 到 n (包括两个)的每个整数在序列中恰好出现一次。
Input
There are multiple test cases. The first line of the input contains an integer T (1≤T≤104) indicating the number of test cases. For each test case:
The first line contains two integers n and f (1≤n≤105, 1≤f≤109) indicating the number of people and the initial position of the elevator.
For the following n lines, the i-th line contains two integers li and ri (1≤li<ri≤109) indicating that the i-th person wants to go from the li-th floor to the ri-th floor by elevator.
It's guaranteed that the sum of n of all test cases will not exceed 3×105.
有道 翻译
输入** **
有多个测试用例。输入的第一行包含一个整数 T ( 1≤T≤104 ),表示测试用例的数量。对于每个测试用例:
第一行包含两个整数 n 和 f ( 1≤n≤105 , 1≤f≤109 ),表示人数和电梯的初始位置。
对于下面的 n 行, i 第一行包含两个整数 li 和 ri ( 1≤li<ri≤109 ),表示第 i 人想乘电梯从 li 到 ri 。
保证所有测试用例 n 的总和不超过 3×105 。
Output
For each test case, first output one line containing one integer indicating the minimum total electric energy, then output another line containing n integers a1,a2,⋯,an separated by a space indicating the optimal order to carry all people. Note that these n integers must form a permutation of n. If there are multiple optimal orders, you can print any of them.
有道 翻译
** **输出
对于每个测试用例,首先输出一行包含一个整数,表示总电能的最小值,然后输出另一行包含 n 个整数 a1,a2,⋯,an ,以空格分隔,表示承载所有人的最优顺序。注意,这些 n 整数必须形成一个 n 的排列。如果有多个最优订单,您可以打印其中的任何一个。
Example
Input
Copy
2
4 2
3 6
1 3
2 7
5 6
2 5
2 4
6 8
Output
Copy
11 2 1 4 3 5 2 1
思路
贪心+模拟。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long t,n,f,l[100005],r[100005],op=0,we[100005],ze[100005],lk=1e18+7,kl=-1;
struct one{
long long l,r,a,b,lr;
}a[100005];
bool cmp(one a1,one b1){
if(a1.r!=b1.r){
return a1.r>b1.r;
}
else{
return a1.l>b1.l;
}
}
//priority_queue<one> qq;
//bool operator<(one a1,one b1){
// return a1.b<b1.b;
//}
int main(){
cin>>t;
while(t--){
cin>>n>>f;
op=0;
for(int i=1;i<=n;i++){
we[i]=-1;
ze[i]=0;
}
for(int i=1;i<=n;i++){
cin>>l[i]>>r[i];
a[i]={l[i],r[i],i,-1,r[i]};
op+=(r[i]-l[i]);
}
sort(a+1,a+n+1,cmp);
we[a[1].a]=0;
for(int i=2;i<=n;i++){
if(a[i].r>=a[i-1].l){
if(a[i-1].l<=a[i-1].lr-1){
a[i].lr=a[i-1].l;
a[i].b=i-1;
}
else{
a[i].lr=a[i-1].lr;
a[i].b=a[i-1].b;
}
we[a[i].a]=we[a[i-1].a];
}
else{
if(a[i-1].l<=a[i-1].lr-1){
a[i].lr=a[i-1].l;
a[i].b=i-1;
we[a[i].a]=we[a[i-1].a]+a[i-1].l-a[i].r;
}
else{
a[i].lr=a[i-1].lr;
a[i].b=a[i-1].b;
we[a[i].a]=we[a[a[i-1].b].a]+max(a[i-1].lr-a[i].r,0ll);
}
}
}
lk=1e18+7;
kl=-1;
for(int i=1;i<=n;i++){
if(max(a[i].l-f,0ll)+we[a[i].a]<=lk-1){
lk=max(a[i].l-f,0ll)+we[a[i].a];
kl=i;
}
}
cout<<op+lk<<endl;
for(int i=kl;i>=0;i=a[i].b){
cout<<a[i].a<<" ";
ze[a[i].a]=1;
}
for(int i=1;i<=n;i++){
if(ze[a[i].a]==0){
cout<<a[i].a<<" ";
}
}
cout<<endl;
}
return 0;
}

浙公网安备 33010602011771号