jzoj1208. 车展(堆)

版权声明:本文为博主原创文章,未经博主允许不得转载。 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);
}

猜你喜欢

转载自blog.csdn.net/zhanghaoxian1/article/details/82812940
今日推荐