Vijos P1459 车展 (treap 任意区间中位数)

题面:

描述

遥控车是在是太漂亮了,韵韵的好朋友都想来参观,所以游乐园决定举办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
Copy

样例输出1

48
Copy

限制

各个测试点1s

提示

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

 

思路:

参考hzwer 博客

 

 

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls t[x].ch[0]
#define rs t[x].ch[1]
const int M = 1e3+10;
const int inf = 0x3f3f3f3f;
ll last[M],n,m,root,cnt,tmp,num,tot;
struct node{
    ll ch[2],cnt,siz,val,rd,sum;
}t[M];

ll a[M],ans[M][M];
void up(ll x){
    t[x].sum = t[ls].sum + t[rs].sum + t[x].cnt*t[x].val;
    t[x].siz = t[ls].siz + t[rs].siz+t[x].cnt;
}

void rotate(ll &x,ll d){
    ll son = t[x].ch[d];
    t[x].ch[d] = t[son].ch[d^1];
    t[son].ch[d^1] = x; up(x); up(x=son);
}

void Insert(ll &x,ll val){
    if(!x){
        x = ++cnt;
        t[x].cnt = t[x].siz = 1;
        t[x].val = t[x].sum = val,t[x].rd = rand();
        ls = 0;rs = 0;  //因为没有清空数组,当前点为新建的点,左右儿子存的是上一次的值,应该清空掉。
        return ;
    }
    t[x].siz ++; t[x].sum += val;
    if(t[x].val == val){
        t[x].cnt++; return ;
    }
    ll d = t[x].val < val; Insert(t[x].ch[d],val);
    if(t[x].rd > t[t[x].ch[d]].rd) rotate(x,d);
}

void del(ll &x,ll val){
    if(!x) return ;
    if(t[x].val == val){
        if(t[x].cnt > 1){
            t[x].cnt--,t[x].siz--;return ;
        }
        bool d = t[ls].rd > t[rs].rd;
        if(ls == 0||rs == 0) x = ls+rs;
        else rotate(x,d),del(x,val);
    }
    else t[x].siz--,del(t[x].ch[t[x].val<val],val);
}

ll query(ll x,ll val){
    if(val <= t[ls].siz) return query(ls,val);
    else if(val > t[ls].siz + t[x].cnt){
        tmp += t[ls].sum + t[x].cnt*t[x].val;
        return query(rs,val-t[ls].siz-t[x].cnt);
    }
    else{
        tmp += t[ls].sum;
        return t[x].val;
    }
}

void solve()
{
    for(ll i = 1;i <= n;i ++){
        cnt = root = tot = 0;
        for(ll j = i;j <= n;j ++){
            tot += a[j];
            Insert(root,a[j]);
            tmp = 0;
            num = (j-i+2)/2;
            ll ave = query(root,num);
            num--;
            ans[i][j] += num*ave - tmp;
            ans[i][j] += tot-tmp-(j-i+1-num)*ave;
        }
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    ll l,r,ans1= 0;
    cin>>n>>m;
    for(ll i = 1;i <= n;i ++) cin>>a[i];
    solve();
    for(ll i = 1;i <= m;i ++){
        cin>>l>>r;
        ans1 += ans[l][r];
    }
    cout<<ans1<<endl;
}

 

上一篇:BZOJ 3435: [Wc2014]紫荆花之恋 【(替罪羊树式)"动态"点分治 + Treap】


下一篇:单调栈求笛卡尔树