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)。
输出格式
一个正整数,调整展台总用时的最小值。
限制
各个测试点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 }
本文为博主原创文章,转载请注明出处。