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

样例输出1[复制]

48

限制

各个测试点1s

提示

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

题解

用treap n^2logn预处理中位数参考hzwer

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N = 1e5+20, M = 1e3+10, MOD = 1e9+7, inf = 2e9;
typedef long long ll;

struct data{int l,r,v,size,rnd,w;ll sum;}tr[N * 4];

int n,siz ,m, a[N],root, ans[M][M] ,Sum,cnt,snt;

void update(int k) {
    tr[k].size = tr[tr[k].l].size+tr[tr[k].r].size + tr[k].w;
    tr[k].sum = tr[tr[k].l].sum + tr[tr[k].r].sum + tr[k].w*tr[k].v;
}
void lturn(int &k) {
    int t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k;update(k);update(t);k=t;
}
void rturn(int &k) {
    int t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k;update(k);update(t);k=t;
}
void insert(int &k,int x) {
    if(!k) {
        k=++siz;
        tr[k].w=tr[k].size=1;
        tr[k].v=tr[k].sum=x;
        tr[k].rnd = rand();
        tr[k].l = tr[k].r =0;
        return ;
    }
    tr[k].size++;tr[k].sum+=x;
    if(tr[k].v==x) tr[k].w++;
    else if(x>tr[k].v) {
        insert(tr[k].r,x);
        if(tr[tr[k].r].rnd<tr[k].rnd) lturn(k);
    }else {
        insert(tr[k].l,x);
        if(tr[tr[k].l].rnd<tr[k].rnd) rturn(k);
    }
}
int query(int k,int x) {
    if(x<=tr[tr[k].l].size) return query(tr[k].l,x);
    else if(x>tr[tr[k].l].size + tr[k].w) {
        cnt+=tr[tr[k].l].size + tr[k].w;
        snt+=tr[tr[k].l].sum+tr[k].w*tr[k].v;
        return query(tr[k].r,x - tr[tr[k].l].size - tr[k].w);
    }else {
        cnt+=tr[tr[k].l].size;
        snt+=tr[tr[k].l].sum;
        return tr[k].v;
    }
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) {
        root = siz = 0;
        Sum = 0;
        for(int j=i;j<=n;j++) {
            Sum += a[j];
            insert(root,a[j]);
            cnt = snt = 0;
            int ave = query(root,(j-i+2) / 2);
            ans[i][j] = cnt*ave - snt + Sum - snt - (j-i+1-cnt)*ave;
        }
    }
    ll all = 0;
    while(m--) {
        int l,r;
        scanf("%d%d",&l,&r);
        all+=ans[l][r];
    }
    cout<<all<<endl;
}
时间: 2024-12-12 17:53:49

Vijos P1459 车展 treap求任意区间中位数的相关文章

SPOJ 1043 Can you answer these queries I 求任意区间最大连续子段和 线段树

题目链接:点击打开链接 维护区间左起连续的最大和,右起连续的和.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lson

vijos P1459车展

P1459车展 Accepted 标签:数据结构 平衡树数据结构 堆重游SC theme Park 描述 遥控车是在是太漂亮了,韵韵的好朋友都想来参观,所以游乐园决定举办m次车展.车库里共有n辆车,从左到右依次编号为1,2,…,n,每辆车都有一个展台.刚开始每个展台都有一个唯一的高度h[i].主管已经列好一张单子:L1 R1L2 R2…Lm Rm单子上的(Li,Ri)表示第i次车展将要展出编号从Li到Ri的车. 为了更加美观,展览时需要调整展台的高度,使参展所有展台的高度相等.展台的高度增加或减

线段树 区间更新(更新区间[x,y]的值,再求任意区间[x,y]的和)

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格--小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问--小Hi给出一段

POJ 3468 区间更新(求任意区间和)A Simple Problem with Integers

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 163977   Accepted: 50540 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type o

hdu 1806 Frequent values(给定一个非降序数组,求任意区间内出现次数最多的数的次数)

1.题目解析可见<训练指南>P198 2代码: #include<cstdio> #include<cstring> #include<cmath> #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define N 100005 #define INF 1<<30 using namespace std; int a[N]; int valu

询问任意区间的min,max,gcd,lcm,sum,xor,or,and

给我们n个数,然后有m个询问,每个询问为L,R,询问区间[L,R]的最大最小值,最小公约数,最大公约数,和,异或,或,且 这些问题通通可以用RMQ的思想来解决. 以下用xor来作为例子 设dp[i][j]为以i开头的,长度为2^j的区间的所有值得异或 那么dp[i][j] = dp[i][j-1] xor dp[i+(1<<(j-1))][j-1] 这样,运用动态规划的思想,我们可以在nlogn的时间复杂度内算出以任意点开头的,长度为1,2,4,8...2^j 的区间的异或值. 那么询问任意区

HDU 4622 Reincarnation( 任意区间子串的长度, 后缀数组+RMQ)

题目大意:给你一个字符串,给你N次查询,每次给你一个区间让你求出这个区间里面有多少子串. 解题思路:我们肯定要枚举位置,然后找公共子串然后再去掉重复的,但是他的地址对应的rank不是连续的,如果暴力找的话会n*n会超时. 从这个博客学习到一种方法:首先对整个字符串求一次sa[]以及height[],之后对于任意区间[L, R],遍历一遍sa[],只要起点在[L, R]内的后缀就需要进行统计,类似于1)中的方法,不过有一个地方要特别注意的就是全部的sa[]不一定就是区间内的sa[],这是因为区间内

求任意多边形的面积(转)

原文地址:http://blog.csdn.net/sun_shine_/article/details/18799739 给定多边形的顶点坐标(有序),让你来求这个多边形的面积,你会怎么做?我们知道,任意多边形都可以分割为N个三角形,所以,如果以这为突破点,那么我们第一步就是把给定的多边形,分割为数个三角形,分别求面积,最后累加就可以了,把多边形分割为三角形的方式多种多样,在这里,我们按照如下图的方法分割: 图1 S点作为起始点(点1),a->e依次作为点2,3…….一个三角形的面积是怎样的呢

FLOyd算法 求任意最短路

此算法由Robert W. Floyd(罗伯特·弗洛伊德)于1962年发表在"Communications of the ACM"上.同年Stephen Warshall(史蒂芬·沃舍尔)也独立发表了这个算法.Robert W.Floyd这个牛人是朵奇葩,他原本在芝加哥大学读的文学,但是因为当时美国经济不太景气,找工作比较困难,无奈之下到西屋电气公司当了一名计算机操作员,在IBM650机房值夜班,并由此开始了他的计算机生涯. 作者:ahalei来源:51CTO博客|2014-03-26