AcWing 2041. 干草堆 ← 差分+桶排序

【题目来源】
https://www.acwing.com/problem/content/2043/

【题目描述】
贝茜对她最近在农场周围造成的一切恶作剧感到抱歉,她同意帮助农夫约翰把一批新到的干草捆堆起来。

开始时,共有 N 个空干草堆,编号 1∼N
约翰给贝茜下达了 K 个指令,每条指令的格式为 A B,这意味着贝茜要在 A..B 范围内的每个
干草堆的顶部添加一个新的干草捆
例如,如果贝茜收到指令 10 13,则她应在干草堆 10,11,12,13 中各添加一个干草捆。
在贝茜完成了所有指令后,约翰想知道 N 个干草堆的
中值高度——也就是说,如果干草堆按照高度从小到大排列,位于中间的干草堆的高度。
方便起见,N 一定是奇数,所以
中间堆是唯一的
请帮助贝茜确定约翰问题的答案。

【输入格式】
第一行包含 N 和 K。
接下来 K 行,每行包含两个整数 A,B,用来描述一个指令。

【输出格式】

输出完成所有指令后,N 个干草堆的中值高度

【数据范围】
1≤N≤
10^6,
1≤K≤25000,
1≤A≤B≤N

【输入样例】
7 4
5 5
2 4
4 6
3 5

【输出样例】
1

【样例解释】
贝茜完成所有指令后,各堆高度为 0,1,2,3,3,1,0。
将各高度从小到大排序后,得到 0,0,1,1,2,3,3,位于中间的是 1。

【算法分析】
差分https://blog.csdn.net/hnjzsyjyj/article/details/132247279
本题
多次对区间进行加减操作,故需用到差分。因为利用差分处理此类“多次对区间进行加减操作”的问题,可以大大降低算法的时间复杂度。这是因为,构造差分数组后,对原数组区间 [le, ri] 的加减操作就转化为对差分数组的区间端点的操作:d[le]+=x,d[ri+1]-=x。这明显大大降低了计算量,所以算法效率会很高。注意:此处的原数组及差分数组的下标都从1开始

--------------------------------------------------- ☆☆​​​​​​​☆​​​​​​​☆​​​​​​​☆ ---------------------------------------------------
示例:
对原数组 a[]=[3 5 9 10 16 18 27] (下标常从 1 开始)的区间 [2,5] 中的每个数都加 3,则等价于对差分数组执行 d[2]+=3,d[5+1]-=3。
验证
(1)首先构建差分数组:设原数组为含有 n 个数的 a 数组(
下标常从 1 开始),差分数组为 d 数组(下标常从 1 开始)。其中,令 d[1]=a[1],且对于 i∈[2,n],令 d[i]=a[i]-a[i-1]
显然,原数组 a[]=[3 5 9 10 16 18 27] (下标常从 1 开始)的差分数组 d[] 构建过程如下:
d[1]=a[1]=3,
d[2]=a[2]-a[1]=5-3=2,
d[3]=a[3]-a[2]=9-5=4,
d[4]=a[4]-a[3]=10-9=1,
d[5]=a[5]-a[4]=16-10=6,
d[6]=a[6]-a[5]=18-16=2,
d[7]=a[7]-a[6]=27-18=9,
即,原数组 a[]=[3 5 9 10 16 18 27] (下标常从 1 开始)的差分数组为 d[]=[3
2 4 1 6 2 9]。
(2)对原数组的区间 [le, ri] 进行加减操作
对原数组 a[]=[3
5 9 10 16 18 27] (下标常从 1 开始)的区间 [2,5] 中的每个数都加 3,得 a[]=[3 8 12 13 19 18 27];而执行 d[2]+=3,d[5+1]-=3 后,得 d[2]=2+3=5,d[6]=2-3=-1,差分数组 d[] 更新为 d=[3 5 4 1 6 -1 9](下标从1开始)。故有:
a[1]=3,
a[2]=d[2]+a[1]=5+3=8,
a[3]=d[3]+a[2]=4+8=12,
a[4]=d[4]+a[3]=1+12=13,
a[5]=d[5]+a[4]=6+13=19,
a[6]=d[6]+a[5]=-1+19=18,

a[7]=d[7]+a[6]=9+18=27,
显然,结论得以验证成立。

-------------------------------------------------------------------------------------------------------------
注意:在代码层面上实践差分算法时,有一个很实用的技巧:若已知差分数组 d[i],则语句 d[i]+=d[i-1] 得到原始数组。即此时更新后的 d[i] 事实上就是之前谈及的原始数组的值。其中,i∈[1,n]。

● 注意本题中,“
干草堆”与“干草捆”的不同陈述。

桶排序https://blog.csdn.net/hnjzsyjyj/article/details/119819927
桶排序的思想:若待排序的值在一个有限范围内(整型)时,可设计有限个有序桶桶号就是待排序的值。之后,将待排序的值依次装入对应的有序桶中(重复值都装入对应的桶),然后顺序输出各桶的值,便得到有序的序列。

#include<bits/stdc++.h>
using namespace std;

const int maxn=500;
int t[maxn];

int main() {
    int n;
    cin>>n;

    int x; //x is less than maxn
    for(int i=1; i<=n; i++) {
        cin>>x;
        t[x]++;
    }

    for(int j=1; j<=maxn; j++) {
        while(t[j]>0) {
            cout<<j<<" ";
            t[j]--;
        }
    }
    return 0;
}

/*
in:
10
20 40 32 67 40 20 89 300 400 15
out:
15 20 20 32 40 40 67 89 300 400
*/


【算法代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e6+5;
int d[maxn];

int main() {
    int n,k;
    cin>>n>>k;
    for(int i=1; i<=k; i++) { //i from 1
        int le,ri;
        cin>>le>>ri;
        d[le]++; //key operation
        d[ri+1]--;
    }

    for(int i=1; i<=n; i++) d[i]+=d[i-1];
    sort(d+1,d+n+1);
    cout<<d[(n+1)>>1]<<endl;

    return 0;
}

/*
in:
7 4
5 5
2 4
4 6
3 5

out:
1
*/




【参考文献】
https://www.acwing.com/solution/content/81274/
https://blog.csdn.net/hnjzsyjyj/article/details/119819927









 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值