标签:
Description
Input
Output
Sample Input
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
Sample Output
Case 1: 3 6 Case 2: 9 18 25
Hint
Case 1: At first ,the information of each hero is 0(1),0(1),0(1) [Exp(level)] After first wave, 1(2),0(1),0(1); After second wave, 3(3),1(2),0(1); After third wave, 6(3),3(3),1(2); Case 2: The information of each hero finally: 18(5) 18(5) 25(5) 5(2) 9(2)
HH出的题,好经典的线段树。转一下大神的解释吧,好经典。
题意很简单,成段更新,成段询问,但是更新却和一般的线段树大不一样,每个点虽然接收到相同的信息,但是由于本身不同,最终得到的值也是不同的.用一般的延迟操作就搞不定了.
突破点在K,范围很小,只有10,可以考虑每次有人升级的时候,就递归的找下去,将这个人进行升级操作.由于找到某个人只需要logn的复杂度,每个人最多升k次,所以n个人的复杂度是O(nklogn)
用了两个辅助数组add[maxn]和MAX[maxk][maxn],add用于记录延迟标记,MAX[k]表示该区间等级为k的最大经验值.初始化add,MAX[1]为0,其他为-1,表示无人在这个等级.当MAX[k]的值大于等于Needk时,就对这个区间进行升级操作,和线段树操作一样递归的将这个区间能升级的人全部升级.
单次操作可能会是nlogn(每个人都升级),但是平均下来还是只有nklogn.
代码:
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<string> #include<cmath> #include<queue> #include<vector> #include<map> #include<set> #define INF 0x3f3f3f3f #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int maxd=10000+5; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1 | 1 typedef long long ll; typedef pair<int,int> pii; //--------------------------- int add[maxd<<2],_max[15][maxd<<2]; int need[15]= {0}; int n,k,op; void pushup(int rt) { for(int i=1; i<=k; ++i) _max[i][rt]=max(_max[i][rt<<1],_max[i][rt<<1|1]); } void pushdown(int rt) { if(add[rt]) { add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; for(int i=1; i<=k; ++i) { if(_max[i][rt<<1]!=-1)/// _max[i][rt<<1]+=add[rt]*i; if(_max[i][rt<<1|1]!=-1) _max[i][rt<<1|1]+=add[rt]*i; } add[rt]=0; } } void build(int l,int r,int rt) { add[rt]=0; if(l==r) { _max[1][rt]=0; for(int i=2; i<=k; ++i) _max[i][rt]=-1; return; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } void levelup(int ki,int l,int r,int rt) { if(l==r) { while(ki<k) { if(_max[ki][rt]>=need[ki]) { _max[ki+1][rt]=_max[ki][rt]; _max[ki][rt]=-1; ++ki; } else break; } return; } pushdown(rt);///?? int m=(l+r)>>1; if(_max[ki][rt<<1] >=need[ki]) levelup(ki,lson); if(_max[ki][rt<<1|1]>=need[ki]) levelup(ki,rson); pushup(rt); } void update(int L,int R,int v,int l,int r,int rt) { if(L<=l && r<=R) { add[rt]+=v; for(int i=k; i>=1; --i) { if(_max[i][rt]!=-1) _max[i][rt]+=v*i; if(i<k && _max[i][rt]>=need[i]) levelup(i,l,r,rt); } return; } pushdown(rt); int m=(l+r)>>1; if(L<=m) update(L,R,v,lson); if(m<R) update(L,R,v,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt) { if(L<=l && r<=R) { for(int i=k; i>=1; --i) if(_max[i][rt]!=-1) return _max[i][rt]; } pushdown(rt); int m=(l+r)>>1; int ret=0; if(L<=m) ret=max(ret,query(L,R,lson)); if(m<R) ret=max(ret,query(L,R,rson)); return ret; } int main() { int kase; freopen("1.txt","r",stdin); scanf("%d",&kase); for(int cas=1; cas<=kase; ++cas) { printf("Case %d:\n",cas); scanf("%d%d%d",&n,&k,&op); build(1,n,1); for(int i=1; i<k; ++i) scanf("%d",&need[i]); while(op--) { char ch[2]; int l,r,val; scanf("%s%d%d",ch,&l,&r); // cout<<ch<<l<<r<<endl; if(ch[0]=='W') { scanf("%d",&val); // cout<<l<<r<<val<<n<<k<<op<<endl; update(l,r,val,1,n,1); } else { printf("%d\n",query(l,r,1,n,1)); } } printf("\n"); } return 0; }
标签:
原文地址:http://blog.csdn.net/whoisvip/article/details/45585065