gym 101201 fast-en J Shopping
来源:互联网 发布:攻心之知错不能改 编辑:程序博客网 时间:2024/05/17 07:28
Problem
Pacific Northwest Region Programming Contest Division 1
https://vjudge.net/contest/188571#problem/J
Meaning
有 n 种物品,编号 1 ~ n,每种
Analysis
朴素的想法,就是每个人都扫一遍他的购买区间,每遇到一种就对价格求余一次,最后剩下的就是答案。
但范围很大,不能暴力。又知道对一个比自己大的数求余是没有任何实际效果的,所以就每次都从区间中找到第一个价格比当前剩余的钱数小的那个物品,买它,然后把区间的左端点更新为该物品的位置。直到区间长度为零,或区间中找不到这样的物品为止。
找区间中第一个比它小的数,可以用线段树记录区间最小值,每次都优先往左找,不行再往下找。注意要保证找到的位置在查询区间内。
还有过另一种想法:用单调栈处理出每种物品的后面第一个价格低于它的物品的位置,在扫区间的时候不暴力扫,而是跳着扫。这样写能过这道题,而且用时更少…但这样在价格序列是降序或基本都是降序的时候没有任何优化效果,故应该不是正解。
Code
正解版
#include <iostream>#include <algorithm>using namespace std;const int N = 200000;long long tree[N<<2|3];inline void pushup(int t){ tree[t] = min(tree[t<<1], tree[t<<1|1]);}int query(long long v, int ql, int qr, int l, int r, int rt){ // 已是叶子 if(l == r) return tree[rt] > v ? -1 : l; // 完全在查询区间内 // 如果 tree[rt] <= v // 则还要往下找 if(ql <= l && r <= qr && tree[rt] > v) return -1; int m = l + r >> 1, pos = -1; // 优先考虑往左找 if(ql <= m) pos = query(v, ql, qr, l, m, rt<<1); // 左边找不到再考虑往右找 if(pos == -1 && qr > m) pos = query(v, ql, qr, m + 1, r, rt<<1|1); return pos;}long long a[N+1];void build(int l, int r, int rt){ if(l == r) { tree[rt] = a[l]; return; } int m = l + r >> 1; build(l, m, rt<<1); build(m + 1, r, rt<<1|1); pushup(rt);}int main(){ ios::sync_with_stdio(false); cin.tie(0); int n, q; cin >> n >> q; for(int i = 1; i <= n; ++i) cin >> a[i]; build(1, n, 1); long long v; for(int l, r; q--; ) { cin >> v >> l >> r; for(int p; v > 0 && l <= r; l = p + 1) { p = query(v, l, r, 1, n, 1); if(p < 0) // 找不到 break; v %= a[p]; } cout << v << '\n'; } return 0;}
单调栈非正解版
#include <iostream>using namespace std;const int N = 200000;long long a[N+11];int nxt[N+11];void make_next(int n){ static int stk[N+1]; int t = 0; for(int i = 1; i <= n; ++i) { while(t > 0 && a[stk[t-1]] > a[i]) { nxt[stk[t-1]] = i; --t; } stk[t++] = i; } while(t-- > 0) nxt[stk[t]] = n + 1;}int main(){ ios::sync_with_stdio(false); cin.tie(0); int n, q; cin >> n >> q; for(int i = 1; i <= n; ++i) cin >> a[i]; make_next(n); for(int l, r; q--; ) { long long v; cin >> v >> l >> r; while(l <= r && a[l] > v) ++l; for( ; v > 0 && l <= r; l = nxt[l]) v %= a[l]; cout << v << '\n'; } return 0;}
阅读全文
0 0
- gym 101201 fast-en J Shopping
- Gym 101201J Shopping(RMQ +二分 )
- Shopping Gym
- Gym 100803C — Shopping
- Gym 100917 J. Judgement
- Gym-100712J-Candy
- Gym 100712J Candy
- Gym 100637J
- Gym 101147.J
- Gym 101243.J
- Gym 101246.J
- Gym 101343.J
- Gym 101617J dp
- GYM 100685 J【交互题】
- Gym 101028J 100541D
- Gym 100851J Jump(构造)
- Gym 100507J Scarily interesting!
- codeforces-gym-100187-J【dfs】
- HYSBZ2648-SJY摆棋子(kd-tree)
- IMU camera IMU 联合标定工具箱使用方法——Kalibr
- teachable-machine:探索机器学习如何工作,浏览器中实时浏览
- hihocoder 1580 Matrix dp+RMQ (带修改的最大子阵和)
- 文章标题
- gym 101201 fast-en J Shopping
- HDU4347-The Closest M Points
- GUI布局
- Android学习-常见的UI控件 RadioGroup和RadioButton
- 深度学习
- 我的六年CSDN博文写作感悟
- mysql简单查询
- 利用ajax请求的post如何传递数据
- 深入浅出的强化学习笔记(二)——使用OpenAI Gym实现游戏AI