车展
2016-07-08 22:41
253 查看
车展
Time Limits: 1000 ms Memory Limits: 65536 KBDescription
遥控车是在是太漂亮了,韵韵的好朋友都想来参观,所以游乐园决定举办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。
题目大意
给出n个高低不同的展台,它可以升降,升一个单位或降一个单位需要1个花费,有给出你m个询问,第i个询问有一个范围[Ai,Bi],现在让你将区间[Ai,Bi]内的每个站台从原来的状况,升降到同一高度,得到一个单次询问花费Vi,求所有Vi的和的最小值。解题思路
因为要得到最小花费,那么变化后的目的高度一定是这个区间的中位数。我们可以先预处理答案,求出每个区间的最小花费总和,在这里,我们可以维护两个堆,第一个堆是小根堆,即小顶堆,存这个区间中比较大的那一半;另一个是大顶堆,存这个区间较小的一半,每次保证小顶堆当前的容量小于等于大顶堆的容量,且容量最多相差1,那么这个区间的中位数就是大顶堆的堆顶。
但我们如果再去一个个升或降的话,就需要O(n)一共O(n^3)<<Boom!!!>><>,于是,我们观察一下计算结果的式子:
∑i=1n|Ai−x|\sum_{i=1}^n |A_i - x|(x为中位数)
假如我们将A小到大排序一下,变成B,那么式子就变为
(x−B1)+(x−B2)+...+(x−Bmid)+(Bmid+1−x)+...+(Bn−1−x)+(Bn−x)(x-B_1)+(x-B_2)+...+(x-B_{mid})+(B_{mid+1}-x)+...+(B_{n-1}-x)+(B_n-x)
转换一下:(∑j=[n2+1]nBj)−(∑i=1[n2]Bi)(\sum_{j=[\frac{n}{2}+1]}^n B_j) - (\sum_{i=1}^{[\frac{n}{2}]} B_i)
发现
当n是偶数时,(∑[n2]i=1Bi)(\sum_{i=1}^{[\frac{n}{2}]} B_i)是小根堆的总和,(∑nj=[n2+1]Bj)(\sum_{j=[\frac{n}{2}+1]}^n B_j)是大根堆的总和
当n是奇数时,(∑[n2]i=1Bi)(\sum_{i=1}^{[\frac{n}{2}]} B_i)是小根堆的总和,(∑nj=[n2+1]Bj)(\sum_{j=[\frac{n}{2}+1]}^n B_j)是大根堆的总和减去中位数
于是乎我们就可以在插入堆的同时维护两个值分别表示较大那个堆(小顶堆)的和,和较小那个堆(大顶堆)的和。
Codes:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define fo(i,x,y) for(int i=x;i<=y;i++) using namespace std; int n,m; long long tot=0,a[1001],maxx[1001],minn[1001],ans[1001][1001],amax,amin; int getmax();//从大顶堆中取出 int getmin();//从小顶堆中取出 void putmax(int);//加入大顶堆 void putmin(int);//加入小顶堆 void upmax(int); void upmin(int); void downmax(int); void downmin(int); int main() { scanf("%d%d",&n,&m); fo(i,1,n)scanf("%lld",&a[i]); fo(i,1,n-1) { memset(minn,0x7f,sizeof(minn)); amin=minn[0]=maxx[0]=0;//初始化堆 maxx[++maxx[0]]=a[i];/*amax和amin为各堆内元素和*/ amax=a[i]; fo(j,i+1,n) { if(maxx[0]==minn[0])//两堆容量相等,在最后使得大顶堆多一 { if(a[j]<minn[1])/*元素要放入大顶堆*/ { putmax(a[j]); amax+=a[j]; }else{/*元素要放到小顶堆的时候,把小顶堆的堆顶移至大顶堆,存入元素*/ int x=getmin(); putmin(a[j]); putmax(x); amax+=x; amin+=a[j]-x; } }else{/*两堆容量不等,在最后使得相等*/ if(maxx[1]>a[j]) { int x=getmax(); putmax(a[j]); putmin(x); amin+=x; amax+=a[j]-x; }else{ putmin(a[j]); amin+=a[j]; } } if((j-i)%2==0) ans[i][j]=ans[j][i]=amin-amax+maxx[1]; else ans[i][j]=ans[j][i]=amin-amax;/*求答案*/ } } fo(i,1,m) { int x,y; scanf("%d%d",&x,&y); tot+=ans[x][y]; } printf("%lld",tot); } int getmax() { int ans=maxx[1]; maxx[1]=maxx[maxx[0]--]; downmax(1); return ans; } int getmin() { int ans=minn[1]; minn[1]=minn[minn[0]--]; downmin(1); return ans; } void putmax(int x) { maxx[++maxx[0]]=x; upmax(maxx[0]); } void putmin(int x) { minn[++minn[0]]=x; upmin(minn[0]); } void upmin(int x) { if(x==1)return; if(minn[x]>=minn[x>>1])return; swap(minn[x>>1],minn[x]); upmin(x>>1); } void upmax(int x) { if(x==1)return; if(maxx[x]<=maxx[x>>1])return; swap(maxx[x>>1],maxx[x]); upmax(x>>1); } void downmax(int x) { if(x*2>maxx[0])return; int a,b=-1; a=maxx[x*2]; if(x*2+1<=maxx[0])b=maxx[x*2+1]; if(maxx[x]<a) { if(a<b) { swap(maxx[x],maxx[x*2+1]); downmax(x*2+1); }else{ swap(maxx[x],maxx[x*2]); downmax(x*2); } }else if(maxx[x]<b) { swap(maxx[x],maxx[x*2+1]); downmax(x*2+1); } } void downmin(int x) { if(x*2>minn[0])return; int a,b=0x7fffffff; a=minn[x*2]; if(x*2+1<=minn[0])b=minn[x*2+1]; if(minn[x]>a) { if(a>b) { swap(minn[x],minn[x*2+1]); downmin(x*2+1); }else{ swap(minn[x],minn[x*2]); downmin(x*2); } }else if(minn[x]>b) { swap(minn[x],minn[x*2+1]); downmin(x*2+1); } }
相关文章推荐
- VS2015 & ReSharper 快捷键设置
- C#调用Java方法
- Android Fragment 生命周期图
- label的富文本设置
- 257. Binary Tree Paths
- SQL查询 生成XML
- 网络爬虫
- golang学习之mgo操作mongodb
- 实用代码块记录2
- syntax error, unexpected T_STRIN
- C 学习之大小端
- 前端组件化思维
- 浅谈Windows 7系统启动过程
- extern "C"
- (3)WSDL文档深入分析
- JS数组
- H.264之编码格式-封装成MP4格式-视频流 RTP封包
- haproxy配置文档
- php rabbitmq操作类及生产者和消费者实例代码
- 错误: Unable to find explicit activity class ...have you declared this activity in your AndroidMa