NOI2010 超级钢琴

题意

小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。 小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最大值是多少。

数据范围

n,k<=500,000
-1000≤Ai≤1000,1≤L≤R≤n
(一定存在满足要求的乐曲)



[Solution]

其实是就是求合法区间中最大的k个区间.

所以全部求出来sort一发就完事了哈哈哈哈哈哈哈
但是好像过不了几组数据.......

不过可以枚举一个右端点,然后去贪左端点(还是比较正常的思路).可以用ST表来维护前缀和,然后对于每个右端点,用ST表来查询合法左端点区间中的最小值.这样就完成了一次操作,然后再把这个右端点删去.

但是多次操作好像会有问题:因为这个右端点还可以选其他左端点.不过其实也没有问题,可以在删除它后把它的左端点区间劈成两半,这样就只去掉了一个点.

实现也很简单,把一个右端点和它对应左端点区间塞进堆里就好了
(这好像是最简单的解法了).

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int M=500005;
const int LG=20;
int sum[M];
struct {
    int id[M][LG],Log[M];
    void Init(int n) {
        Log[0]=-1;
        for
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值