题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3954
题目大意:
有n个人站一排,有m次操作,每个人最多可以到达k级,给出升级所需到达的经验
操作:w——【a,b】区间每个人都会获得(等级level * 经验k)的经验,q——求区间【a,b】内经验值最多的人有多少经验。
如果经验满足升级条件,那么人物的等级level将会升级。最高等级为k级,人物的初始等级为1级
算法:线段树
思路:如果区间有可以升级的,更新到底~~每个结点记录升级所需要的最少【基】经验,最大等级,最大经验;在PushUp中返回最大等级,最大经验,以及最小基经验,在pushdown中下放add,下放基经验,下放sum[rt << 1] += add[rt] * level[rt << 1];
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> using namespace std; #define lson l, m, rt << 1 #define rson m+1, r, rt << 1 | 1 #define mid int m = (l+r) >> 1 int n, mm, K; int lev[15]; int level[80000], sum[80000], les[80000], add[80000]; int minz(int a, int b) { return a < b ? a : b; } int maxz(int a, int b) { return a > b ? a : b; } void PushUp(int rt) { les[rt] = minz(les[rt << 1], les[rt << 1 | 1]); sum[rt] = maxz(sum[rt << 1], sum[rt << 1 | 1]); level[rt] = maxz(level[rt << 1], level[rt << 1 | 1]); } void PushDown(int rt) { if(add[rt]) { add[rt << 1] += add[rt]; add[rt << 1 | 1] += add[rt]; les[rt << 1] -= add[rt]; les[rt << 1 | 1] -= add[rt]; sum[rt << 1] += add[rt] * level[rt << 1]; sum[rt << 1 | 1] += add[rt] * level[rt << 1 | 1]; add[rt] = 0; } } void build(int l, int r, int rt) { level[rt] = 1; sum[rt] = 0; les[rt] = lev[1]; if(l == r) { return ; } mid ; build(lson); build(rson); } void update(int L, int R, int k, int l, int r, int rt) { // printf("rt = %d\n", rt); if(L <= l && r <= R) { if(les[rt] <= k && l != r) { PushDown(rt); mid ; update(L, R, k, lson); update(L, R, k, rson); PushUp(rt); }//×ÓÊ÷Éý¼¶ else if(l == r) { sum[rt] += k * level[rt]; int i = level[rt]; while(lev[i ++] <= sum[rt]) level[rt] = i; les[rt] = lev[level[rt]] - sum[rt]; les[rt] = (les[rt] - 1) / level[rt] + 1;//ÐèÒª×îÉÙ¾Ñé } else { sum[rt] += k * level[rt]; add[rt] += k; les[rt] -= k; } return ; } mid ; PushDown(rt); if(L <= m) update(L, R, k, lson); if(m < R) update(L, R, k, rson); PushUp(rt); } int query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { return sum[rt]; } mid ; int ret = 0; PushDown(rt); if(L <= m) ret = maxz(ret, query(L, R, lson)); if(m < R) ret = maxz(ret, query(L, R, rson)); return ret ; } int main() { int T; scanf("%d", &T); int ica = 1; while(T --) { printf("Case %d:\n", ica ++); scanf("%d%d%d", &n, &K, &mm); memset(add, 0, sizeof(add)); lev[0] = 0; int i; for(i = 1; i < K; i ++) { scanf("%d", &lev[i]); } lev[i] = 0x7fffffff; build(1, n, 1); int a, b, c; char op[4]; while(mm --) { scanf("%s%d%d", op, &a, &b); if(op[0] == 'W') { scanf("%d", &c); update(a, b, c, 1, n, 1); } else { printf("%d\n", query(a, b, 1, n, 1)); } } printf("\n"); } return 0; }