Level up
http://acm.hdu.edu.cn/showproblem.php?pid=3954
In a online game, there are N heroes numbered id from 1 to N, each begins with level 1 and 0 Experience. They need to kill monsters to get Exp and level up.
There are many waves of monsters, each wave, the heroes with id from li to ri will come to kill monsters and those hero with level k will get ei*k Exp. If one hero's Exp reach Needk then the hero level up to level k immediately.
After some waves, I will query the maximum Exp from li to ri.
Now giving the information of each wave and Needk, please tell me the answer of my query.
The first line of each case contains three integers N(1<=N<=10000), K(2<=K<=10) and QW(1<=QW<=10000)each represent hero number, the MAX level and querys/waves number.
Then a line with K -1 integers, Need2, Need3...Needk.(1 <= Need2 < Need3 < ... < Needk <= 10000).
Then QW lines follow, each line start with 'W' contains three integers li ri ei (1<=li<=ri<=N , 1<=ei<=10000); each line start with 'Q' contains two integers li ri (1<=li<=ri<=N).
For each query, output the maximum Exp from li to ri.
Output a black line after each case.
2 3 3 5 1 2 W 1 1 1 W 1 2 1 Q 1 3 W 1 3 1 Q 1 3 5 5 8 2 10 15 16 W 5 5 9 W 3 4 5 W 1 1 2 W 2 3 2 Q 3 5 W 1 3 8 Q 1 2 Q 3 5
Case 1: 3 6 Case 2: 9 18 25
题意:每次会给[a,b]中的英雄加上ei*k(k为英雄的当前等级)的经验,同时英雄有了一定经验也会升级,问[a,b]中最大的经验是多少。
题解:maxx[i]表示等级为i的人的经验的最大值,那么我们就知道每个等级上是否有人的经验达到了升级条件,一旦有人达到就直接找到这个人,并将路径上的max[i]和max[i+1]的值更新一下即可。由于K比较小,每个人最多升级K次,而每次找一个人的复杂度是logN,所以升级操作总的复杂度是K*N*logN。
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 10005
#define inf ((1<<30)-1)
//#define max(a,b) ((a)>(b)?(a):(b))
int max(int a,int b)
{
return a>b?a:b;
}
int maxx[MAX<<2][11],add[MAX<<2],need[11];
int k;
void build(int l,int r,int idx)
{
memset(maxx[idx],-1,sizeof(maxx[idx]));
maxx[idx][1]=add[idx]=0;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,idx<<1);
build(mid+1,r,idx<<1|1);
}
void push_up(int idx)
{
for(int i=1; i<=k; ++i)
maxx[idx][i]=max(maxx[idx<<1][i],maxx[idx<<1|1][i]);
}
void push_down(int idx)
{
if(add[idx])
{
add[idx<<1]+=add[idx];
add[idx<<1|1]+=add[idx];
for(int i=1; i<=k; ++i)
{
if(maxx[idx<<1][i]!=-1)
maxx[idx<<1][i]+=(i*add[idx]);
if(maxx[idx<<1|1][i]!=-1)
maxx[idx<<1|1][i]+=(i*add[idx]);
}
add[idx]=0;
}
}
void change(int k,int l,int r,int idx)
{
if(l==r)
{
maxx[idx][k+1]=maxx[idx][k];
maxx[idx][k]=-1;
return;
}
int mid=(l+r)>>1;
push_down(idx);
if(maxx[idx<<1][k]>=need[k])
change(k,l,mid,idx<<1);
else
change(k,mid+1,r,idx<<1|1);
maxx[idx][k]=max(maxx[idx<<1][k],maxx[idx<<1|1][k]);
maxx[idx][k+1]=max(maxx[idx<<1][k+1],maxx[idx<<1|1][k+1]);
}
void update(int a,int b,int c,int l,int r,int idx)
{
if(a<=l&&r<=b)
{
add[idx]+=c;
for(int i=1; i<=k; ++i)
if(maxx[idx][i]!=-1)
maxx[idx][i]+=(i*c);
for(int i=1; i<k; ++i)
for(; maxx[idx][i]>=need[i];)
change(i,l,r,idx);
return;
}
push_down(idx);
int mid=(l+r)>>1;
if(a<=mid) update(a,b,c,l,mid,idx<<1);
if(b>mid) update(a,b,c,mid+1,r,idx<<1|1);
push_up(idx);
}
int query(int a,int b,int l,int r,int idx)
{
int ans=0;
if(a<=l&&r<=b)
{
for(int i=k; i>0; --i)
if(maxx[idx][i]!=-1)
{
ans=maxx[idx][i];
break;
}
return ans;
}
push_down(idx);
int mid=(l+r)>>1;
if(a<=mid)
ans=max(ans,query(a,b,l,mid,idx<<1));
if(b>mid)
ans=max(ans,query(a,b,mid+1,r,idx<<1|1));
return ans;
}
inline void scan(int &n)
{
char cc ;
for(;cc=getchar(),cc<'0'||cc>'9';);
n=cc-'0';
for(;cc=getchar(),cc>='0'&&cc<='9';)
n=n*10+cc-'0';
}
int main()
{
int t,n,qw,a,b,c;
char s[5];
scanf("%d",&t);
for(int tt=1; tt<=t; ++tt)
{
scanf("%d%d%d",&n,&k,&qw);
for(int i=1; i<k; ++i)
scanf("%d",&need[i]);
need[k]=inf;
build(1,n,1);
printf("Case %d:\n",tt);
for(; qw--;)
{
scanf("%s",s);
if(s[0]=='W')
{
//scanf("%d%d%d",&a,&b,&c);
scan(a);scan(b);scan(c);
update(a,b,c,1,n,1);
}
else
{
//scanf("%d%d",&a,&b);
scan(a);scan(b);
printf("%d\n",query(a,b,1,n,1));
}
}
puts("");
}
return 0;
}
1万+



被折叠的 条评论
为什么被折叠?



