首页 > 代码库 > Vijos1459 车展 (数学)

Vijos1459 车展 (数学)

 

描述

遥控车是在是太漂亮了,韵韵的好朋友都想来参观,所以游乐园决定举办m次车展。车库里共有n辆车,从左到右依次编号为1,2,…,n,每辆车都有一个展台。刚开始每个展台都有一个唯一的高度h[i]。主管已经列好一张单子:
L1 R1
L2 R2

Lm Rm
单子上的(Li,Ri)表示第i次车展将要展出编号从Li到Ri的车。

为了更加美观,展览时需要调整展台的高度,使参展所有展台的高度相等。展台的高度增加或减少1都需花费1秒时间。由于管理员只有一个人,所以只好对每个展台依次操作。每次展览结束后,展台高度自动恢复到初始高度。

请告诉管理员为了举办所有展览,他最少需要花多少时间将展台调整好。

格式

输入格式

第一行为两个正整数n、m。

第二行共n个非负整数,表示第i辆车展台的高度h[i]。

接下来m行每行2个整数Li、Ri(Li≤Ri)。

输出格式

一个正整数,调整展台总用时的最小值。

样例1

样例输入1[复制]

 
6 44 1 2 13 0 91 52 63 42 2

样例输出1[复制]

 
48

限制

各个测试点1s

提示

对于50%的数据 n≤500,m≤1000;
对于80%的数据 n≤1000,m≤100000;
对于100%的数据n≤1000,m≤200000;
答案在2^64以内。

来源

birdor

 

分析可知,将高度都调整成区间中位数时,代价最小。

枚举i作为中心,向两边扩展序列。

先扩展左边,用链表记录每个“大于a[i]的数比小于a[i]的数多x”的位置po1。

再扩展右边,用右边的每个“大于a[i]的数比小于a[i]的数少x”的位置po2,匹配之前左边记录的位置,则mid[po1][po2]=i

之后O(n^2)暴力累加调整高度的花费。

 

 1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=1010;10 int read(){11     int x=0,f=1;char ch=getchar();12     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}13     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();}14     return x*f;15 }16 int pre[mxn],id[mxn],m[mxn<<2];17 int mid[mxn][mxn];18 int a[mxn];19 int n,Q;20 int main(){21     n=read();Q=read();22     int i,j;23     for(i=1;i<=n;i++){a[i]=read();}24     for(i=1;i<=n;i++){25         memset(id,0,sizeof id);26         memset(m,-1,sizeof m);27         memset(pre,0,sizeof pre);28         int x=0,d=0,cnt=1;29         for(j=i;j;j--){30             if(a[j]>a[i])d++;31             else x++;32             id[cnt]=j;33             pre[cnt]=m[d-x+mxn];34             m[d-x+mxn]=cnt++;35         }36         d=0;x=-1;37         for(j=i;j<=n;j++){38             if(a[j]>a[i])d++;39             else x++;40             for(int k=m[x-d+mxn];k!=-1;k=pre[k]){41                 if( (j-id[k]+1)%2==0 )mid[id[k]][j]=a[i];42             }43             for(int k=m[x-d-1+mxn];k!=-1;k=pre[k]){44                 if( (j-id[k])%2==0 )mid[id[k]][j]=a[i];45             }46         }47     }48     int st,ed;49     long long ans=0;50     while(Q--){51         st=read();ed=read();52         long long res=0;53 //        printf("mid:%d\n",mid[st][ed]);54         for(i=st;i<=ed;i++)res+=abs(a[i]-mid[st][ed]);55 //        printf("%d\n",res);56         ans+=res;57     }58     printf("%lld\n",ans);59     return 0;60 }

 

Vijos1459 车展 (数学)