您的位置:首页 > 其它

HDU 3954 Level up

2012-04-12 17:10 423 查看
HDU_3954

一开始始终在纠结要怎样维护max,因为不同等级的人每次加的经验是不一样的,这样如果只用一个max来维护最大值的话是很难办的。看了胡浩的出题报告之后恍然大悟,既然一个max来维护是很难办的,那不妨就将max变成K个,max[i]表示等级为i的人的经验的最大值,这样max[i]的增加就很好处理了。

至于如何处理一个人的升级问题,既然有了max[i],那么我们就知道每个等级上是否有人的经验达到了need[i+1],一旦有人达到就直接找到这个人,并将路径上的max[i]和max[i+1]的值更新一下即可。由于K比较小,每个人最多升级K次,而每次找一个人的复杂度是logN,所以升级操作总的复杂度是K*N*logN,是可以接受的。查询操作就比较好写了。

#include<stdio.h>
#include<string.h>
#define MAXD 10010
#define MAXK 11
#define INF 0x3f3f3f3f
int N, K, QW, max[4 * MAXD][MAXK], add[4 * MAXD], need[MAXK];
void build(int cur, int x, int y)
{
int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
memset(max[cur], -1, sizeof(max[cur]));
max[cur][1] = add[cur] = 0;
if(x == y)
return ;
build(ls, x, mid);
build(rs, mid + 1, y);
}
void init()
{
int i;
scanf("%d%d%d", &N, &K, &QW);
for(i = 1; i < K; i ++)
scanf("%d", &need[i]);
need[K] = INF;
build(1, 1, N);
}
int getmax(int x, int y)
{
return x > y ? x : y;
}
void update(int cur)
{
int i, ls = cur << 1, rs = (cur << 1) | 1;
for(i = 1; i <= K; i ++)
max[cur][i] = getmax(max[ls][i], max[rs][i]);
}
void pushdown(int cur)
{
int ls = cur << 1, rs = (cur << 1) | 1;
if(add[cur])
{
int i;
add[ls] += add[cur], add[rs] += add[cur];
for(i = 1; i <= K; i ++)
{
if(max[ls][i] != -1)
max[ls][i] += i * add[cur];
if(max[rs][i] != -1)
max[rs][i] += i * add[cur];
}
add[cur] = 0;
}
}
void change(int cur, int x, int y, int k)
{
int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
if(x == y)
{
max[cur][k + 1] = max[cur][k];
max[cur][k] = -1;
return ;
}
pushdown(cur);
if(max[ls][k] >= need[k])
change(ls, x, mid, k);
else
change(rs, mid + 1, y, k);
max[cur][k] = getmax(max[ls][k], max[rs][k]);
max[cur][k + 1] = getmax(max[ls][k + 1], max[rs][k + 1]);
}
void refresh(int cur, int x, int y, int s, int t, int delta)
{
int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
if(x >= s && y <= t)
{
int i;
add[cur] += delta;
for(i = 1; i <= K; i ++)
if(max[cur][i] != -1)
max[cur][i] += i * delta;
for(i = 1; i < K; i ++)
while(max[cur][i] >= need[i])
change(cur, x, y, i);
return ;
}
pushdown(cur);
if(mid >= s)
refresh(ls, x, mid, s, t, delta);
if(mid + 1 <= t)
refresh(rs, mid + 1, y, s, t, delta);
update(cur);
}
void query(int cur, int x, int y, int s, int t, int &ans)
{
int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
if(x >= s && y <= t)
{
int i;
for(i = 1; i <= K; i ++)
if(max[cur][i] > ans)
ans = max[cur][i];
return ;
}
pushdown(cur);
if(mid >= s)
query(ls, x, mid, s, t, ans);
if(mid + 1 <= t)
query(rs, mid + 1, y, s, t, ans);
}
void solve()
{
int i, j, k, x, y, z, ans;
char b[5];
for(i = 0; i < QW; i ++)
{
scanf("%s", b);
if(b[0] == 'W')
{
scanf("%d%d%d", &x, &y, &z);
refresh(1, 1, N, x, y, z);
}
else
{
scanf("%d%d", &x, &y);
ans = 0;
query(1, 1, N, x, y, ans);
printf("%d\n", ans);
}
}
}
int main()
{
int t, tt;
scanf("%d", &t);
for(tt = 0; tt < t; tt ++)
{
init();
printf("Case %d:\n", tt + 1);
solve();
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: