//线段树 //WA了很多次,最后查出原因居然是建树的时候初始化有最大糖果的下标错了 //我只有在叶子节点有初始化,其他点没有,所以错了,正确初始化应该是每个区间最左边的点为maxid //线段树插入和修改的inherit和update函数是关键,直到这道题总算摸索出套路了 //建树什么都差不多,关键就看如何识别标记,如何处理区间与区间之间关系,如何回溯传递结果 #include<iostream> #define MAX 100005 using namespace std; struct seg { int l,r,_max,_maxid,add; }tree[4 * MAX]; int index,x,y,add,_maxCandy,N,M; char cmd; void buildTree(int fa,int l,int r) { tree[fa].l = l; tree[fa].r = r; tree[fa]._max = tree[fa].add = 0; tree[fa]._maxid = l; if(l == r) return; int mid = (l + r) >> 1; buildTree(2*fa,l,mid); buildTree(2*fa+1,mid+1,r); } void inherit(int fa)//读取当前结点的add,并将这一信息传递给左右子树 { tree[2*fa].add += tree[fa].add; tree[2*fa+1].add += tree[fa].add; tree[2*fa]._max += tree[fa].add; tree[2*fa+1]._max += tree[fa].add; tree[fa].add = 0;//注意传递好后就清除ADD的情况,对搜索到的区间,ADD只能增加一次 } void update(int fa)//回溯时更新父结点的信息 { tree[fa]._max = max(tree[2*fa]._max,tree[2*fa+1]._max);//看左右子树哪个最大 tree[fa]._maxid = tree[2*fa]._max >= tree[2*fa+1]._max ? tree[2*fa]._maxid : tree[2*fa+1]._maxid;//哪个最大就记录那个的ID,优先记录左子树 } void insert(int fa,int l,int r,int add) { if(tree[fa].l == l && tree[fa].r == r) { tree[fa].add += add; tree[fa]._max += add; return; } inherit(fa); int mid = (tree[fa].l + tree[fa].r) >> 1; if(r <= mid) insert(2*fa,l,r,add); else if(l > mid) insert(2*fa+1,l,r,add); else { insert(2*fa,l,mid,add); insert(2*fa+1,mid+1,r,add); } update(fa); } void search(int fa,int l,int r) { if(tree[fa].l == l && tree[fa].r == r) { if(tree[fa]._max == _maxCandy) index = (tree[fa]._maxid,index); if(tree[fa]._max > _maxCandy) { _maxCandy = tree[fa]._max; index = tree[fa]._maxid; } return; } inherit(fa); int mid = (tree[fa].l + tree[fa].r) >> 1; if(r <= mid) search(2*fa,l,r); else if(l > mid) search(2*fa+1,l,r); else { search(2*fa,l,mid); search(2*fa+1,mid+1,r); } update(fa); } int main() { while(scanf("%d%d",&N,&M) && N) { buildTree(1,1,N); while(M--) { scanf("/n%c",&cmd); if(cmd == 'I') { scanf("%d%d%d",&x,&y,&add); insert(1,x,y,add); } else { _maxCandy = 0;//最大糖果数量 index = N;//拥有最大糖果堆的下表 scanf("%d%d",&x,&y); search(1,x,y);//搜索改区间 printf("%d/n",_maxCandy); if(_maxCandy != 0) insert(1,index,index,-_maxCandy);//利用插入的方法,插入个负的,把糖拿出来,如果最大的是0那就不用修改了,省点时间 } } } return 0; }