2006: [NOI2010]超级钢琴 ST表+优先队列
2016-04-11 08:22
369 查看
来补几发题解吧…从HN集训回来也做了几道题一直没发题解。
我们首先求出前缀和,然后枚举左端点l,右端点的所在范围就是[l+L−1,l+R−1],然后我们要求出这段区间内的最大值,然后加入堆里。每次取出堆顶元素,假设为区间[l..x],然后再把区间[l+L−1,x−1],[x+1,l+R−1]的最大值分别加入堆里。然后重复m此获得答案。
我们首先求出前缀和,然后枚举左端点l,右端点的所在范围就是[l+L−1,l+R−1],然后我们要求出这段区间内的最大值,然后加入堆里。每次取出堆顶元素,假设为区间[l..x],然后再把区间[l+L−1,x−1],[x+1,l+R−1]的最大值分别加入堆里。然后重复m此获得答案。
#include<iostream> #include<cstdio> #include<cmath> #include<queue> #define N 500005 using namespace std; struct data { int i,l,r,t; }; int n,K,L,R; long long ans; int a ,f [20]; inline bool operator<(data x,data y) { return a[x.t]-a[x.i-1]<a[y.t]-a[y.i-1]; } inline int query(int l,int r) { int k=log2(r-l+1); int t1=f[l][k],t2=f[r-(1<<k)+1][k]; if (a[t1]>a[t2]) return t1; else return t2; } inline void solve() { priority_queue<data> q; for (int i=1;i<=n-L+1;i++) { int j=min(n,i+R-1); q.push((data){i,i+L-1,j,query(i+L-1,j)}); } for (int i=1;i<=K;i++) { data now=q.top(); q.pop(); ans+=a[now.t]-a[now.i-1]; if (now.t-1>=now.l) q.push((data){now.i,now.l,now.t-1,query(now.l,now.t-1)}); if (now.t+1<=now.r) q.push((data){now.i,now.t+1,now.r,query(now.t+1,now.r)}); } } int main() { scanf("%d%d%d%d",&n,&K,&L,&R); for (int i=1;i<=n;i++) { int x; scanf("%d",&x); a[i]=a[i-1]+x; } for (int i=1;i<=n;i++) f[i][0]=i; for (int j=1;j<=18;j++) for (int i=1;i<=n;i++) if (i+(1<<j)-1<=n) { int t1=f[i][j-1],t2=f[i+(1<<(j-1))][j-1]; if (a[t1]<a[t2]) f[i][j]=t2; else f[i][j]=t1; } solve(); cout << ans << endl; }
相关文章推荐
- 搜索 第一题 二分问题
- 87 智能指针(一)
- 设计模式之单例模式
- TextKit简单示例
- iOS学习笔记03-UITableView
- 深度学习卷积神经网络大事件一览
- iOS学习笔记02-UIScrollView
- HDU 4927 Series 1
- centos 搭建gitlab
- NET通用平台
- 使用Highcharts生成折线图_at last
- vi快捷键必知必会
- 左旋转字符串
- 【Hdu 5661】 Claris and XOR 位运算+贪心
- FMDB基本使用
- C语言文件遍历
- 贪心总结
- Activiti5 开发介绍1
- iOS学习笔记16-数据库SQLite
- 超详细cordova环境配置(windows)及实例