【BZOJ2006】[NOI2010]超级钢琴 ST表+堆
【BZOJ2006】[NOI2010]超级钢琴
Description
Input
Output
只有一个整数,表示乐曲美妙度的最大值。
Sample Input
3
2
-6
8
Sample Output
【样例说明】
共有5种不同的超级和弦:
音符1 ~ 2,美妙度为3 + 2 = 5
音符2 ~ 3,美妙度为2 + (-6) = -4
音符3 ~ 4,美妙度为(-6) + 8 = 2
音符1 ~ 3,美妙度为3 + 2 + (-6) = -1
音符2 ~ 4,美妙度为2 + (-6) + 8 = 4
最优方案为:乐曲由和弦1,和弦3,和弦5组成,美妙度为5 + 2 + 4 = 11。
题解:一开始想用主席树,然后越想越觉得做麻烦了,于是看题解发现用ST表就行。
我们先考虑较暴力的写法(最暴力的肯定是n2logn),假如我们已经确定了所选区间的右端点,那么我们能否快速知道最优的左端点是哪个呢?显然可以,我们将区间和转变为前缀相减的形式,求[l,r]的最大值也就是求s[r]-s[l-1]的最大值,因为r确定,而l只能在一段固定的区间,我们可以用ST表快速查询最小值。然后我们对于每个可行的右端点都找出最优的左端点,把它们扔到优先队列里一个一个取出来就行了。
但是问题来了,加入我们取出了点x,它的最优最短点y,那么在我们取出了y后,以后就不能再取y这个点了,那么我们该怎样将y删除呢?一个naive的想法就是用主席树,但是这要麻烦不少。
我们的目的就是想办法避免删除操作(因为ST表是不支持修改的),我们发现,加入原来x的左端点可以在[a,b]中选择,我们与其从[a,b]中去掉y,不如将[a,b]分裂成[a,y-1]和[y+1,b]两段,然后将这两段都扔到优先队列中。也就是说,我们在优先队列中存放的其实是一个四元组(sum,x,a,b),分别代表区间和,右端点,合法左端点的区间最左边和最右边。
代码真的巨短。
- #include <cstdio>
- #include <iostream>
- #include <queue>
- #include <cstring>
- #include <utility>
- #define mp(A,B,C,D) make_pair(make_pair(A,B),make_pair(C,D))
- using namespace std;
- typedef pair<int,int> pii;
- priority_queue<pair<pii,pii> > pq;
- int n,m,L,R;
- long long ans;
- const int maxn=500010;
- int sn[maxn][20],v[maxn],s[maxn],Log[maxn];
- int rd()
- {
- int ret=0,f=1; char gc=getchar();
- while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
- while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
- return ret*f;
- }
- int mn(int a,int b)
- {
- return s[a]<s[b]?a:b;
- }
- int query(int a,int b)
- {
- if(a>b) return -1;
- int k=Log[b-a+1];
- return mn(sn[a][k],sn[b-(1<<k)+1][k]);
- }
- int main()
- {
- n=rd(),m=rd(),L=rd(),R=rd();
- int i,j,x,y,a,b,c,d;
- for(i=2;i<=n;i++) Log[i]=Log[i>>1]+1;
- for(i=1;i<=n;i++) sn[i][0]=i,v[i]=rd(),s[i]=v[i]+s[i-1];
- for(j=1;(1<<j)<=n;j++)
- for(i=0;i+(1<<j)-1<=n;i++)
- sn[i][j]=mn(sn[i][j-1],sn[i+(1<<j-1)][j-1]);
- for(i=L;i<=n;i++) pq.push(mp(s[i]-s[query(max(i-R,0),i-L)],i,max(i-R,0),i-L));
- for(i=1;i<=m;i++)
- {
- pii t1=pq.top().first,t2=pq.top().second;
- ans+=t1.first,x=t1.second,a=t2.first,b=t2.second,y=query(a,b),pq.pop();
- c=query(a,y-1),d=query(y+1,b);
- if(c!=-1) pq.push(mp(s[x]-s[c],x,a,y-1));
- if(d!=-1) pq.push(mp(s[x]-s[d],x,y+1,b));
- }
- printf("%lld",ans);
- return 0;
- }
【BZOJ2006】[NOI2010]超级钢琴 ST表+堆的更多相关文章
- [BZOJ2006][NOI2010]超级钢琴(ST表+堆)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3679 Solved: 1828[Submit][Statu ...
- 【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2473 Solved: 1211[Submit][Statu ...
- BZOJ 2006: [NOI2010]超级钢琴 ST表+堆
开始想到了一个二分+主席树的 $O(n\log^2 n)$ 的做法. 能过,但是太无脑了. 看了一下题解,有一个 ST 表+堆的优美解法. 你发现肯定是选取前 k 大最优. 然后第一次选的话直接选固定 ...
- bzoj 2006 [NOI2010]超级钢琴——ST表+堆
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006 每个右端点的左端点在一个区间内:用堆记录端点位置.可选区间,按价值排序:拿出一个后也许 ...
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...
- BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表
BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐 ...
- bzoj2006 [NOI2010]超级钢琴 (及其拓展)
bzoj2006 [NOI2010]超级钢琴 给定一个序列,求长度在 \([L,\ R]\) 之间的区间和的前 \(k\) 大之和 \(n\leq5\times10^5,\ k\leq2\times1 ...
- BZOJ2006 [NOI2010]超级钢琴 【堆 + RMQ】
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MB Submit: 3446 Solved: 1692 [Submit][Sta ...
- P2048 [NOI2010]超级钢琴(RMQ+堆+贪心)
P2048 [NOI2010]超级钢琴 区间和--->前缀和做差 多次查询区间和最大--->前缀和RMQ 每次取出最大的区间和--->堆 于是我们设个3元组$(o,l,r)$,表示左 ...
随机推荐
- Mongodb副本集+分片集群环境部署
前面详细介绍了mongodb的副本集和分片的原理,这里就不赘述了.下面记录Mongodb副本集+分片集群环境部署过程: MongoDB Sharding Cluster,需要三种角色: Shard S ...
- DatagramPacket,DatagramSocket
package test; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSo ...
- Spark map-side-join 关联优化
在spark中要进行join操作,如果在shuffle的时候进行join效率较低.如果满足 所需要join的表中有一张表较小,那么可以考虑在map端进行join操作. 转载:http://blog.c ...
- ElasticSearch高级查询
ElasticSearch高级查询 https://www.imooc.com/video/15759/0 ElasticSearch查询 1,子条件查询:特定字段查询所指特定值 1.1query c ...
- spring 配置多数据源 (可行)
可以看到AbstractRoutingDataSource获取数据源之前会先调用determineCurrentLookupKey方法查找当前的lookupKey,这个lookupKey就是数据源标识 ...
- Binder与interface
在Interface中,asBinder函数涌来将服务类接口类型转换为IBinder类型: 相反的,asInterface函数用来将Ibinder类型转换为服务接口类型
- 雷锋沙龙 ppt 演讲内容分享(xss,流量劫持的利用)
http://www.pkav.net/XSS.png?from=timeline&isappinstalled=0
- windows pip源
首先在window的文件夹窗口输入 : %APPDATA% 然后在底下新建pip文件夹,然后到pip文件夹里面去新建个pip.ini,然后再里面输入内容 [global] timeout = 6000 ...
- 微信小程序 - 一种简写方式
// 第一种 isOrder: function() { //code }, // 第二种 isOrders() { //code },
- Python内置模块和第三方模块
1.Python内置模块和第三方模块 内置模块: Python中,安装好了Python后,本身就带有的库,就叫做Python的内置的库. 内置模块,也被称为Python的标准库. Python 2.x ...