【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
2
3
4
5
6
6 4
4 1 2 13 0 9
1 5
2 6
3 4
2 2
样例输出1
1
48
限制

各个测试点1s

提示

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

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 1005
#define ll long long
int n,cnt,rt,m;
int size[N],h[N],ans[N][N],ls[N],rs[N];
ll tot,anstot,tmp,num;
ll w[N],rnd[N],v[N],sum[N];
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void update(int k)
{
    size[k]=size[ls[k]]+size[rs[k]]+w[k];
    sum[k]=sum[ls[k]]+sum[rs[k]]+v[k]*w[k];
}
inline void rturn(int &k)
{
    int t=ls[k];ls[k]=rs[t];rs[t]=k;
    update(k);update(t);k=t;
}
inline void lturn(int &k)
{
    int t=rs[k];rs[k]=ls[t];ls[t]=k;
    update(k);update(t);k=t;
}
inline void insert(int &k,int x)
{
    if (k==0)
    {
        k=++cnt;
        sum[k]=v[k]=x;
        size[k]=w[k]=1;
        rnd[k]=rand();
        ls[k]=rs[k]=0;
        return;
    }
    size[k]++;sum[k]+=x;
    if (v[k]==x) w[k]++;
    else if (v[k]<x)
    {
        insert(rs[k],x);
        if (rnd[rs[k]]<rnd[k]) lturn(k);
    }
    else
    {
        insert(ls[k],x);
        if (rnd[ls[k]]<rnd[k]) rturn(k);
    }
} 
int query(int k,int val)
{
    if (val<=size[ls[k]]) return query(ls[k],val);
    else if (val>size[ls[k]]+w[k])
    {
        tmp+=sum[ls[k]]+w[k]*v[k];
        num+=size[ls[k]]+w[k];
        return query(rs[k],val-size[ls[k]]-w[k]);
    }
    else
    {
        tmp+=sum[ls[k]];
        num+=size[ls[k]];
        return v[k];
    }
}
inline void solve()
{
    for (int i=1;i<=n;i++)
    {
        cnt=rt=tot=0;
        for (int j=i;j<=n;j++)
        {
            tot+=h[j];
            insert(rt,h[j]);
            tmp=num=0;
            int ave=query(rt,(j-i+2)/2);
            ans[i][j]+=num*ave-tmp;
            ans[i][j]+=tot-tmp-(j-i+1-num)*ave;
        }
    }
}

int main()
{
    n=read();m=read();
    for (int i=1;i<=n;i++) h[i]=read();
    solve();
    for (int i=1;i<=m;i++)
    {
        int l=read(),r=read();
        anstot+=ans[l][r];
    }
    printf("%lld",anstot);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值