hdu 3954--线段树

http://acm.hdu.edu.cn/showproblem.php?pid=3954

题意:有N个英雄,每个英雄的初始等级为1,初始经验为0,有K个等级,QW个操作。接下来一行中有K-1个数值,代表升到等级2,等级3……所要达到的经验。接下来的QW行里,每行是一个操作,操作有两类,(1)"l r e",代表区间[l,r]里的每个英雄将得到e乘以他的等级的经验。(2)"l r",表示查询区间[l,r]里经验最大值。

思路:这题因为加的经验跟等级有关,所以不能用普通的惰性标记。应该往什么时候区间内加的经验是一样的方向思考???刚开始思考的时候是想着区间内都满级的时候加的经验就一样了,但是这样写依旧超时。。后来网上搜了一下,忽略了区间内如果没有英雄升级时加的经验也是一样多了,然后再加上这个判断条件就Ok了。一开始写挫了,无限超时,不过我对线段树的惰性标记倒是又增加了不少认识。方法:用sjmin存区间内升级需要的最少经验,djmax存区间内的最大等级,flag作为惰性标记,如果没有英雄升级的话可以暂时不用把经验往下传,Max存区间内的最大经验。而因为每个英雄的增加经验跟等级有关,所以sjmin的计算方法是用距离下一等级的经验除以当前等级,然后向上取整。

代码:

复制代码
View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 using namespace std;
  4 #define lson l,m,rt<<1
  5 #define rson m+1,r,rt<<1|1
  6 #define maxn 55555
  7 int Max[maxn<<2],flag[maxn<<2],sjmin[maxn<<2],djmax[maxn<<2],jy[15];
  8 int max(int a,int b)
  9 {
 10     return a>b?a:b;
 11 }
 12 int min(int a,int b)
 13 {
 14     return a<b?a:b;
 15 }
 16 void Pushup(int rt)
 17 {
 18     Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
 19     sjmin[rt]=min(sjmin[rt<<1],sjmin[rt<<1|1]);
 20     djmax[rt]=max(djmax[rt<<1],djmax[rt<<1|1]);
 21 }
 22 void Pushdown(int rt)
 23 {
 24     flag[rt<<1]+=flag[rt];
 25     flag[rt<<1|1]+=flag[rt];
 26     Max[rt<<1]+=djmax[rt<<1]*flag[rt];
 27     Max[rt<<1|1]+=djmax[rt<<1|1]*flag[rt];
 28     sjmin[rt<<1]-=flag[rt];
 29     sjmin[rt<<1|1]-=flag[rt];
 30     flag[rt]=0;
 31 }
 32 void build(int l,int r,int rt)
 33 {
 34     Max[rt]=0;
 35     djmax[rt]=1;
 36     sjmin[rt]=jy[2];
 37     flag[rt]=0;
 38     if(l==r)
 39         return ;
 40     int m=(l+r)>>1;
 41     build(lson);
 42     build(rson);
 43 }
 44 void update(int L,int R,int w,int l,int r,int rt)
 45 {
 46     if(L<=l&&r<=R)
 47     {
 48         if(sjmin[rt]>w)
 49         {
 50             Max[rt]+=djmax[rt]*w;
 51             flag[rt]+=w;
 52             sjmin[rt]-=w;
 53             return ;
 54         }
 55         else if(l==r)
 56         {
 57             Max[rt]+=djmax[rt]*w;
 58             while(Max[rt]>=jy[djmax[rt]+1])
 59                 djmax[rt]++;
 60             sjmin[rt]=(jy[djmax[rt]+1]-Max[rt])/djmax[rt]+((jy[djmax[rt]+1]-Max[rt])%djmax[rt]!=0);
 61             return ;
 62         }
 63     }
 64     Pushdown(rt);
 65     int m=(l+r)>>1;
 66     if(L<=m) update(L,R,w,lson);
 67     if(R>m) update(L,R,w,rson);
 68     Pushup(rt);
 69 }
 70 int query(int L,int R,int l,int r,int rt)
 71 {
 72     if(L<=l&&r<=R)
 73         return Max[rt];
 74     Pushdown(rt);
 75     int m=(l+r)>>1;
 76     int ret=0;
 77     if(L<=m) ret=max(ret,query(L,R,lson));
 78     if(R>m) ret=max(ret,query(L,R,rson));
 79     return ret;
 80 }
 81 int main()
 82 {
 83     int t,n,m,dj,cas=1;
 84     scanf("%d",&t);
 85     while(t--)
 86     {
 87         scanf("%d %d %d",&n,&dj,&m);
 88         for(int i=2;i<=dj;i++)
 89             scanf("%d",&jy[i]);
 90         jy[1]=0;jy[i]=1<<30;
 91         build(1,n,1);
 92         char ch[10];
 93         int a,b,c;
 94         printf("Case %d:\n",cas++);
 95         while(m--)
 96         {
 97             scanf("%s",ch);
 98             if(ch[0]=='W')
 99             {
100                 scanf("%d %d %d",&a,&b,&c);
101                 update(a,b,c,1,n,1);
102             }
103             else
104             {
105                 scanf("%d %d",&a,&b);
106                 printf("%d\n",query(a,b,1,n,1));
107             }
108         }
109         puts("");
110     }
111     return 0;
112 }
复制代码

 

posted on 2013-02-21 12:01  acoderworld  阅读(325)  评论(0)    收藏  举报

努力加载评论中...

导航

点击右上角即可分享
微信分享提示