(2017多校2)1003/hdu-6047 Maximum Sequence(单调队列/优先队列)
来源:互联网 发布:西班牙手机网络 编辑:程序博客网 时间:2024/06/08 11:19
点我看题
题意:分别给出两个序列a和b,根据规则
官方题解:预处理:a_i -= i ,易证明从最小的b开始选每次选最大的一定可以使结果最大。 证明思路:如果条件改为a_i<=max{a_j-j|b_k<=j<=n},那么b的顺序与最后的结果无关。条件改回来后,由于每次要计算一个数的最大值时都有a_(n+1)...a_(i-1)在范围中,所以每次只需让a_i - i尽可能大,那么就把大的数尽早用上,每次一定考虑尽量多的数字,这样取得的数字就尽可能的大。 所以说每次就是求区间最值,加在答案上。由于贪心的思路,每次要求的区间的下界是单调不降的,故可以用单调队列优化到O(n)的复杂度。 由于1 ≤ b_i ≤ n,对b排序可以用哈希排序(桶排序)完成。
进一步观察,可以发现这样贪心时 a_(n+1)...a_i 其实是单调不增的,所以并不需要每次求区间最值了,选第一个数时就选最大的,后面的选择顺序与最终结果无关了
分析:Contest的时候用优先队列写的,当时比较担心超时,后来想想应该也不会超时,因为进队出队的过程都是O(log2n),不过后来发现用单调队列更节约时间.
参考代码:
//优先队列
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<string>#include<algorithm>#include<queue>#include<stack>#include<set>#include<map>#include<vector>using namespace std;typedef long long ll;const int maxn = 250010;const int mod = 1e9+7;int n;int a[maxn];int b[maxn];struct Node{ int val; int id; friend bool operator < ( const Node &a, const Node &b) { if( a.val != b.val) return a.val < b.val; return a.id > b.id; }};priority_queue<Node> q;int main(){ while( ~scanf("%d",&n)) { while( !q.empty()) q.pop(); Node tmp; for( int i = 1; i <= n; i++) { scanf("%d",&a[i]); tmp.id = i; tmp.val = a[i]-i; q.push(tmp); } for( int i = 1; i <= n; i++) scanf("%d",&b[i]); sort(b+1,b+1+n); ll ans = 0; int p = 1; while( p <= n) { tmp = q.top(); while( b[p] > tmp.id) { q.pop(); tmp = q.top(); } ans=(ans+tmp.val)%mod; tmp.val -= (n+p); tmp.id = n+p; q.push(tmp); p++; } printf("%lld\n",ans); } return 0;}
//单调队列
#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<iostream>using namespace std;#define LL long longconst int mod = 1e9+7;const int maxn = 250010;int n;int a[maxn];int b[maxn];struct Node{ int id; int val;};Node q[maxn<<1];int main(){ while( ~scanf("%d",&n)) { int head = 0; int tail = 0; for( int i = 1; i <= n; i++) { scanf("%d",&a[i]); if( tail == 0) { q[tail].id = i; q[tail++].val = a[i]-i; } else { while( head < tail && a[i]-i >= q[tail-1].val) tail--; q[tail].id = i; q[tail++].val = a[i]-i; } } for( int i = 1; i <= n; i++) scanf("%d",&b[i]); sort(b+1,b+1+n); int p = 1; Node tmp; LL ans = 0; while( p <= n) { while( b[p] > q[head].id) head++; ans = (ans+q[head].val)%mod; tmp.id = p+n; tmp.val = q[head].val-(n+p); while( head < tail && tmp.val >= q[tail-1].val) tail--; q[tail++] = tmp; p++; } printf("%lld\n",ans); } return 0;}
阅读全文
0 0
- (2017多校2)1003/hdu-6047 Maximum Sequence(单调队列/优先队列)
- 【HDU 6047 Maximum Sequence】 + 优先队列
- Hdu 6047 Maximum Sequence【贪心+优先队列】
- 2017 杭电多校联赛第二场 1003 Maximum Sequence(单调队列)HDU 6047
- 【2017多校】 Maximum Sequence 【优先队列】
- HDOJ 6047 Maximum Sequence(单调队列)
- 2017 多校训练第二场 HDU 6047 Maximum Sequence(贪心+优先队列)
- Maximum Sequence 贪心 优先队列
- hdu 2757 单调优先队列 bfs
- HDU 6047 优先队列
- 【优先队列】:poj2442,Sequence
- Sequence(优先队列)
- HDU Max Sum of Max-K-sub-sequence(单调队列)
- POj 2823 单调队列 / 优先队列
- poj2823单调队列(模拟优先队列)
- hdu 1506#单调队列
- hdu 4193#单调队列
- HDU 4193 单调队列
- 动态规划? 最大连续子序列和
- 面试中的一些必须知道的简单知识
- Python中接口定义和依赖注入
- postgresql复制
- 1002 Biorhythms
- (2017多校2)1003/hdu-6047 Maximum Sequence(单调队列/优先队列)
- STM32用到的几种存储器
- bosten key party 2017 memo writeup
- CS231n课程笔记翻译7:神经网络笔记 part2
- 【POJ 1088】滑雪
- 数据结构基础知识-线性表
- 0727Link
- 锁定Excel
- CSS之float