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 4
4 1 2 13 0 9
1 5
2 6
3 4
2 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
",mid[st][ed]);
54         for(i=st;i<=ed;i++)res+=abs(a[i]-mid[st][ed]);
55 //        printf("%d
",res);
56         ans+=res;
57     }
58     printf("%lld
",ans);
59     return 0;
60 }