当前位置: 代码迷 >> 综合 >> HDU 6315 -2018 Multi-University Training Contest 2:Naive Operations
  详细解决方案

HDU 6315 -2018 Multi-University Training Contest 2:Naive Operations

热度:16   发布时间:2023-12-01 21:51:50.0

一开始做这个题目的时候,一直想不出来,怎么用线段树来进行维护信息
看了大佬们的代码后,终于知道怎么弄了
好菜啊我
很高兴,又学习了一种线段树的新姿势

首先线段树结构体中维护这几个信息:
结点区间中a的最大值 - maxa
结点区间中b的最小值 - minb
结点区间的延迟更新标记 - addv
结点区间的值 - cnt

每次更新区间 [L,R]
当区间 [L,R] 包含 线段树某个结点的区间时
我们是否要更新该结点的全部孩子结点呢?肯定是不要的,不然复杂度也接受不了
首先我们要更新该结点的maxa
当该结点更新后的maxa还是小于该结点的minb,就不需要更新该结点的孩子结点,只需要延迟更新标记addv更新一下即可,因为该结点的值 cnt 不可能要更新啊
还有就是当该结点没有孩子结点,也就是该结点是叶子结点时,不需要进行下一步更新,并且当叶子结点的maxa不小于minb,说明叶子结点的值cnt要更新了,并且叶子结点的minb要变成minb+b[ind] ,ind为叶子结点代表的点,这些地方得自己好好想一想,我觉得很妙,这种方法

这样线段树就可以维护这个题目的信息了

要是还是不太懂,就看代码吧,我也是看代码看懂的
详细请看代码:

#include<cstdio>
using namespace std;#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
const int maxn=100000+100;
struct Tree{int maxa,minb;int addv;int cnt;
}tree[maxn<<2];int b[maxn];inline void PushDown(int root){if(tree[root].addv){int addv=tree[root].addv;tree[root].addv=0;tree[root<<1].addv+=addv;tree[root<<1].maxa+=addv;tree[root<<1|1].addv+=addv;tree[root<<1|1].maxa+=addv;}
}inline void PushUp(int root){tree[root].maxa=max(tree[root<<1].maxa,tree[root<<1|1].maxa);tree[root].minb=min(tree[root<<1].minb,tree[root<<1|1].minb);tree[root].cnt=tree[root<<1].cnt+tree[root<<1|1].cnt;
}inline void Build(int l,int r,int root){tree[root].addv=0;if(l==r){tree[root].maxa=0;tree[root].minb=b[l];tree[root].cnt=0;return ;}int mid=(l+r)>>1;Build(l,mid,root<<1);Build(mid+1,r,root<<1|1);PushUp(root); 
} inline void Update(int l,int r,int L,int R,int root){if(L<=l && R>=r){tree[root].maxa++;if(tree[root].maxa<tree[root].minb){tree[root].addv++;return ;}if(l==r && tree[root].maxa>=tree[root].minb){tree[root].cnt++;tree[root].minb+=b[l];return ;}if(l==r) return ;}PushDown(root);int mid=(l+r)>>1;if(L<=mid) Update(l,mid,L,R,root<<1);if(R>mid) Update(mid+1,r,L,R,root<<1|1);PushUp(root);
}inline int Query(int l,int r,int L,int R,int root){if(L<=l && R>=r){return tree[root].cnt;}PushDown(root);int mid=(l+r)>>1;int ans=0;if(L<=mid) ans+=Query(l,mid,L,R,root<<1);if(R>mid) ans+=Query(mid+1,r,L,R,root<<1|1);return ans; 
}int main(){int n,q;char ch[20];int l,r;while(scanf("%d%d",&n,&q)==2){for(int i=1;i<=n;i++) scanf("%d",&b[i]);Build(1,n,1);while(q--){scanf("%s %d %d",ch,&l,&r);if(ch[0]=='a') Update(1,n,l,r,1);else printf("%d\n",Query(1,n,l,r,1));}}
}
  相关解决方案