哈理工OJ1524-最大
线段树题目,给出一个序列,查询一段a,b之间的最大的连续相同的数字的和最大是多少,定义为MS,因为对于一个区间的MS,可能来自于左子节点或者右子节点,或者当左节点最右面的数字和右节点的左面的数字相同时可能会来自两个节点合并的部分,所以,树中的节点要维护五个基本的值,lval(最左侧的值),lnum(最左侧值连续的个数),rval(最右侧的值),rnum(最右侧值连续的个数)以及MS,为了提高效率,还要增加一个标记值,不需要更新每一个节点。
View Code
#include<iostream> #include<cstdio> #include<cstring> #define N 100005 #define L(x) x<<1 #define R(x) x<<1|1 using namespace std; int val[N]; int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a<b?a:b; } struct node { int l,r; int lval,rval; int lnum,rnum; int Ms; int f; }; node tree[4*N]; void build(int l,int r,int i) { tree[i].l=l; tree[i].r=r; tree[i].f=-1;//初始化为-1,更新的值有可能是0 tree[i].Ms=0; if(l==r) { tree[i].lval=tree[i].rval=tree[i].Ms=tree[i].f=val[l]; tree[i].lnum=tree[i].rnum=1; return; } int mid=(l+r)>>1; build(l,mid,L(i)); build(mid+1,r,R(i)); tree[i].lval=tree[L(i)].lval; tree[i].rval=tree[R(i)].rval; if(tree[L(i)].lnum==mid-l+1&&tree[R(i)].lval==tree[L(i)].lval) tree[i].lnum=tree[L(i)].lnum+tree[R(i)].lnum; else tree[i].lnum=tree[L(i)].lnum; if(tree[R(i)].rnum==r-mid&&tree[L(i)].rval==tree[R(i)].rval) tree[i].rnum=tree[R(i)].rnum+tree[L(i)].rnum; else tree[i].rnum=tree[R(i)].rnum; tree[i].Ms=max(tree[L(i)].Ms,tree[R(i)].Ms); if(tree[L(i)].rval==tree[R(i)].lval) tree[i].Ms=max(tree[i].Ms,tree[L(i)].rval*(tree[L(i)].rnum+tree[R(i)].lnum)); } void update(int l,int r,int v,int i) { if(tree[i].l==l&&tree[i].r==r) { tree[i].lval=tree[i].rval=v; tree[i].lnum=tree[i].rnum=r-l+1; tree[i].f=v; tree[i].Ms=(r-l+1)*v; return; } if(tree[i].f!=-1) { tree[L(i)].lval=tree[L(i)].rval=tree[i].f; tree[R(i)].lval=tree[R(i)].rval=tree[i].f; tree[L(i)].lnum=tree[L(i)].rnum=tree[L(i)].r-tree[L(i)].l+1; tree[R(i)].lnum=tree[R(i)].rnum=tree[R(i)].r-tree[R(i)].l+1; tree[L(i)].Ms=tree[L(i)].lval*tree[L(i)].lnum; tree[R(i)].Ms=tree[R(i)].lval*tree[R(i)].lnum; tree[L(i)].f=tree[R(i)].f=tree[i].f; tree[i].f=-1; } int mid=(tree[i].l+tree[i].r)>>1; if(r<=mid) update(l,r,v,L(i)); else if(l>mid) update(l,r,v,R(i)); else { update(l,mid,v,L(i)); update(mid+1,r,v,R(i)); } tree[i].lval=tree[L(i)].lval; tree[i].rval=tree[R(i)].rval; if(tree[L(i)].lnum==mid-tree[i].l+1&&tree[R(i)].lval==tree[L(i)].lval) tree[i].lnum=tree[L(i)].lnum+tree[R(i)].lnum; else tree[i].lnum=tree[L(i)].lnum; if(tree[R(i)].rnum==tree[i].r-mid&&tree[L(i)].rval==tree[R(i)].rval) tree[i].rnum=tree[R(i)].rnum+tree[L(i)].rnum; else tree[i].rnum=tree[R(i)].rnum; tree[i].Ms=max(tree[L(i)].Ms,tree[R(i)].Ms); if(tree[L(i)].rval==tree[R(i)].lval) tree[i].Ms=max(tree[i].Ms,tree[L(i)].rval*(tree[L(i)].rnum+tree[R(i)].lnum)); } int query(int l,int r,int i) { if(tree[i].l==l&&tree[i].r==r) { return tree[i].Ms; } int ans1,ans2,ans3; ans1=ans2=ans3=0; if(tree[i].f!=-1) { tree[L(i)].lval=tree[L(i)].rval=tree[i].f; tree[R(i)].lval=tree[R(i)].rval=tree[i].f; tree[L(i)].lnum=tree[L(i)].rnum=tree[L(i)].r-tree[L(i)].l+1; tree[R(i)].lnum=tree[R(i)].rnum=tree[R(i)].r-tree[R(i)].l+1; tree[L(i)].Ms=tree[L(i)].lval*tree[L(i)].lnum; tree[R(i)].Ms=tree[R(i)].lval*tree[R(i)].lnum; tree[L(i)].f=tree[R(i)].f=tree[i].f; tree[i].f=-1; } int mid=(tree[i].l+tree[i].r)>>1; if(r<=mid) ans1=query(l,r,L(i)); else if(l>mid) ans2=query(l,r,R(i)); else { ans1=query(l,mid,L(i)); ans2=query(mid+1,r,R(i)); if(tree[L(i)].rval==tree[R(i)].lval) ans3=tree[L(i)].rval*(min(tree[L(i)].rnum,mid-l+1)+min(tree[R(i)].lnum,r-mid)); } //printf("%d %d %d %d %d %d\n",l,r,i,ans1,ans2,ans3); ans1=max(ans1,ans2); ans1=max(ans1,ans3); return ans1; } int main() { int n,m,i,j; int icase=0; int op,a,b,c; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) scanf("%d",&val[i]); build(1,n,1); printf("Case %d:\n",++icase); scanf("%d",&m); while(m--) { scanf("%d",&op); if(op==1) { scanf("%d%d%d",&a,&b,&c); update(a,b,c,1); } else { scanf("%d%d",&a,&b); printf("%d\n",query(a,b,1)); } } } return 0; }