poj 2892 hdu1540 线段树 求过某点的最大连续区间。

来源:互联网 发布:网络教育学历有用吗 编辑:程序博客网 时间:2024/05/16 10:36

其他与平常的区间合并无异处。

最大难度的地方就是query函数的写法。

见代码。代码注释。

附图理解。

#include <cstdio>#include <stack>#include <algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int Max=50010;int maxn[Max<<2],lmaxn[Max<<2],rmaxn[Max<<2],cov[Max<<2];void pushup(int rt,int m){    lmaxn[rt]=lmaxn[rt<<1];rmaxn[rt]=rmaxn[rt<<1|1];if(lmaxn[rt]==m-(m>>1)) lmaxn[rt]+=lmaxn[rt<<1|1];if(rmaxn[rt]==(m>>1))rmaxn[rt]+=rmaxn[rt<<1];maxn[rt]=max(max(maxn[rt<<1],maxn[rt<<1|1]),lmaxn[rt<<1|1]+rmaxn[rt<<1]);}void build(int l,int r,int rt){maxn[rt]=lmaxn[rt]=rmaxn[rt]=r-l+1;    if(l==r)return ;int m=(l+r)>>1;build(lson);build(rson);pushup(rt,r-l+1);}void update(int c,int k,int l,int r,int rt){if(l==r){maxn[rt]=lmaxn[rt]=rmaxn[rt]=k;return ;}int m=(l+r)>>1;if(c<=m) update(c,k,lson);else update(c,k,rson);pushup(rt,r-l+1);}int query(int c,int l,int r,int rt){    if(l==r||maxn[rt]==r-l+1||maxn[rt]==0)return maxn[rt];int m=(l+r)>>1;if(c<=m){if(c>=m-rmaxn[rt<<1]+1)  //如果点位于左子树的右连续区间上,则可能要和右子树的左连续区间合并。return query(c,lson)+query(m+1,rson);else    //点位于左子树的左连续区间上。无需合并return query(c,lson);}if(c>m){    if(c<=m+lmaxn[rt<<1|1])  //如果点位于右子树的左连续区间上,则可能需要和左子树的右连续区间合并。return query(m,lson)+query(c,rson);else  //点位于右子树的右连续区间。无需合并。return query(c,rson);}}int main(){    int n,m,a;scanf("%d %d",&n,&m);build(1,n,1);char ch[2];stack<int >k;while(m--){    scanf("%s%d",ch,&a);if(ch[0]=='D'){update(a,0,1,n,1);k.push(a);}else if(ch[0]=='R'){int t=k.top();update(t,1,1,n,1);k.pop();}else if(ch[0]=='Q')printf("%d\n",query(a,1,n,1));}return 0;}

第一种情况 ,需要和右子树的左连续区间合并。

 

第二种,无需合并。

第三种,

需要和左子树的右连续区间合并。

第四种。。。。

0 0
原创粉丝点击