HDU 2795 单点更新 + 区间最值

来源:互联网 发布:公钥密码算法 编辑:程序博客网 时间:2024/05/18 22:54

HDU 2795




这题有点特殊, 要在查询的时候更新, 而且 因为是找最小的行数, 所以非左即右,优先考虑左(存在解情况下)



AC code:

#include <cstdio>#include <cstring>#include <cmath>#include <queue>#include<algorithm>using namespace std;#define debug 0#define inf 0x3f3f3f3f#define mid ((l + r) >> 1)#define ls  rt << 1, l, mid#define rs  rt << 1 | 1, mid + 1, rconst int maxn = 200000 + 5;int len[maxn << 2], h, w, n;//线段树数组存储, 左右孩子的最小的行宽void pushUp(int rt) {len[rt] = min(len[rt << 1], len[rt << 1 | 1]);          //上移}void build(int rt, int l, int r) {if (l == r) {len[rt] = 0;//建树,初始化每行的宽度都为0return;}build(ls);build(rs);pushUp(rt);}int query(int temp, int rt, int l, int r) {if (l == r) {len[rt] += temp;//找到最小行数, 更新该行宽度//update(1, 1, h);return l;}int res;res = len[rt << 1] + temp <= w ? query(temp, ls) : query(temp, rs);//有解, 非左即右, 优先左pushUp(rt);//查询时更新。return res;}int main(){#if debugfreopen("in.txt", "r", stdin);#endif //debugint pl;while (~scanf("%d%d%d", &h, &w, &n)) {memset(len, inf, sizeof(len));h = min(h, n);build(1, 1, h);while (n--) {scanf("%d", &pl);if (pl + len[1] > w) {//如果最小的行宽不满足, 输出-1puts("-1");}else {//最小行宽满足, 一定有解int ans = query(pl, 1, 1, h);if (ans == inf)//额这两个语句可以省了ans = -1;printf("%d\n", ans);}}}return 0;}






1 0