hdu 3954(区间更新)
2015-10-30 16:12
260 查看
题意:有n个人,每个人初始等级是1,初始经验值是0,一共有K个等级,给出到达每个等级需要的经验值,然后有q个操作,W l r e把第l个人到第r个人的经验值都加上其对应的等级×e,Q l r询问l到r人中经验值的最大值。
题解:刚开始用单点修改把每个人经验值改掉,毫无疑问的超时了,然后就想怎么把每个人获得不同的经验值在区间表示,苦逼的想不出来,然后看了题解。。。因为要维护区间最大经验值,所以就维护一个最小到下一等级需要的经验值need,need[k] = (下一等级经验值-当前经验值) / 当前等级 + 余数 ,这样消除不同等级的人所加经验值的不同。
题解:刚开始用单点修改把每个人经验值改掉,毫无疑问的超时了,然后就想怎么把每个人获得不同的经验值在区间表示,苦逼的想不出来,然后看了题解。。。因为要维护区间最大经验值,所以就维护一个最小到下一等级需要的经验值need,need[k] = (下一等级经验值-当前经验值) / 当前等级 + 余数 ,这样消除不同等级的人所加经验值的不同。
#include <cstdio> #include <cstring> #include <algorithm> #define ll long long using namespace std; const int N = 10005; int level[N << 2], n, K, q; ll Exp[N << 2], need[N << 2], flag[N << 2], ex[15]; void pushup(int k) { Exp[k] = max(Exp[k * 2], Exp[k * 2 + 1]); level[k] = max(level[k * 2], level[k * 2 + 1]); need[k] = min(need[k * 2], need[k * 2 + 1]); } void pushdown(int k) { if (flag[k]) { Exp[k * 2] += flag[k] * level[k * 2]; need[k * 2] -= flag[k]; flag[k * 2] += flag[k]; Exp[k * 2 + 1] += flag[k] * level[k * 2 + 1]; need[k * 2 + 1] -= flag[k]; flag[k * 2 + 1] += flag[k]; flag[k] = 0; } } void build(int k, int left, int right) { need[k] = ex[2]; Exp[k] = flag[k] = 0; level[k] = 1; if (left != right) { int mid = (left + right) / 2; build(k * 2, left, mid); build(k * 2 + 1, mid + 1, right); } } void modify(int k, int left, int right, int l, int r, ll v) { if (l <= left && right <= r) { if (v >= need[k]) { if (left == right) { Exp[k] += level[k] * v; while (Exp[k] >= ex[level[k] + 1]) level[k]++; ll temp = ex[level[k] + 1] - Exp[k]; need[k] = temp / level[k] + (temp % level[k] != 0); } else { pushdown(k); int mid = (left + right) / 2; if (l <= mid) modify(k * 2, left, mid, l, r, v); if (r > mid) modify(k * 2 + 1, mid + 1, right, l, r, v); pushup(k); } } else { Exp[k] += v * level[k]; need[k] -= v; flag[k] += v; } return; } pushdown(k); int mid = (left + right) / 2; if (l <= mid) modify(k * 2, left, mid, l, r, v); if (r > mid) modify(k * 2 + 1, mid + 1, right, l, r, v); pushup(k); return; } ll query(int k, int left, int right, int l, int r) { if (l <= left && right <= r) return Exp[k]; pushdown(k); int mid = (left + right) / 2; ll res = 0; if (l <= mid) res = max(res, query(k * 2, left, mid, l, r)); if (r > mid) res = max(res, query(k * 2 + 1, mid + 1, right, l, r)); pushup(k); return res; } int main() { int t, cas = 1; scanf("%d", &t); ex[1] = 0; while (t--) { scanf("%d%d%d", &n, &K, &q); for (int i = 2; i <= K; i++) scanf("%lld", &ex[i]); ex[K + 1] = (ll)(1 << 30); build(1, 1, n); char op[5]; int l, r; ll e; printf("Case %d:\n", cas++); while (q--) { scanf("%s%d%d", op, &l, &r); if (op[0] == 'W') { scanf("%lld", &e); modify(1, 1, n, l, r, e); } else { printf("%lld\n", query(1, 1, n, l, r)); } } printf("\n"); } return 0; }
相关文章推荐
- 最小树形图*
- JavaScript 调用 CSS 属性
- java1.8--Null Object模式
- 基于openfire+smack开发Android即时聊天应用[一]---openfire安装部署
- Hibernate教程 class2
- CSS定位属性之间的相互作用
- svn: The log message is a pathname (was -F intended?)
- django 注册、登录及第三方接口程序(1):基础知识
- java1.8--Null Object模式
- JSP EL表达式 param、paramValues的使用
- 一份标准的HTML文档必须有的HTML标签
- 第十一课 for循环(3)---循环变量的变化
- 第11章 对话框
- 调试 vs2010 assert()断言对话框的使用
- 栈的应用之表达式求值(算符优先法)
- java调用批处理(doc)执行多条命令
- uploadify+jcrop实现头像上传裁剪功能
- 堆
- 第20章 多任务和多线程
- PL/SQL下载安装