版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhanghaoxian1/article/details/82812940
1208. 车展
Description
遥控车是在是太漂亮了,韵韵的好朋友都想来参观,所以游乐园决定举办m次车展。车库里共有n辆车,从左到右依次编号为1,2,…,n,每辆车都有一个展台。刚开始每个展台都有一个唯一的高度h[i]。主管已经列好一张单子:
L1 R1
L2 R2
…
Lm Rm
单子上的(Li,Ri)表示第i次车展将要展出编号从Li到Ri的车。
为了更加美观,展览时需要调整展台的高度,使参展所有展台的高度相等。展台的高度增加或减少1都需花费1秒时间。由于管理员只有一个人,所以只好对每个展台依次操作。每次展览结束后,展台高度自动恢复到初始高度。
请告诉管理员为了举办所有展览,他最少需要花多少时间将展台调整好。
Input
第一行为两个正整数n、m。
第二行共n个非负整数,表示第i辆车展台的高度h[i]。
接下来m行每行2个整数Li、Ri(Li≤Ri)。
Output
一个正整数,调整展台总用时的最小值。
Sample Input
6 4
4 1 2 13 0 9
1 5
2 6
3 4
2 2
Sample Output
48
Hint
【数据规模和约定】
对于50%的数据 n≤500,m≤1000;
对于80%的数据 n≤1000,m≤100000;
对于100%的数据n≤1000,m≤200000;
答案小于2^64。
分析:每个区间的最小代价显然是全部变成中位数,然后用堆求中位数即可。
代码
#include <cstdio>
#include <queue>
#define ll long long
#define N 200005
using namespace std;
struct arr
{
int h,num;
}a[N];
priority_queue<int> maxq;
priority_queue<int> minq;
int n,m;
ll ans[1005][1005];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i].h);
a[i].num = i;
}
ll sum1, sum2;
for (int i = 1; i <= n; i++)
{
sum1 = sum2 = 0;
while (minq.size()) minq.pop();
while (maxq.size()) maxq.pop();
for (int j = i; j <= n; j++)
{
if (minq.size() == maxq.size())
{
maxq.push(a[j].h);
sum1 += a[j].h;
}
else
{
minq.push(-a[j].h);
sum2 += a[j].h;
}
if (maxq.size() && minq.size())
{
int minx = -minq.top();
int maxx = maxq.top();
if (minx < maxx)
{
minq.pop();
maxq.pop();
minq.push(-maxx);
maxq.push(minx);
sum1 = sum1 - maxx + minx;
sum2 = sum2 - minx + maxx;
}
}
int mid = maxq.top();
int siz1 = maxq.size();
int siz2 = minq.size();
ans[i][j] = (siz1 * mid - sum1) + (sum2 - siz2 * mid);
}
}
ll sum = 0;
for (int i = 1; i <= m; i++)
{
int x,y;
scanf("%d%d", &x, &y);
sum += ans[x][y];
}
printf("%lld", sum);
}