Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4437 Accepted Submission(s): 2006
线段树区间合并
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define N 100005 struct node { int l,r,m; int ln,rn; int lsum,rsum,msum; int mid() { return (l+r)>>1; } }t[N<<2]; int a[N]; void pushup(int rt) { t[rt].lsum=t[rt<<1].lsum; t[rt].rsum=t[rt<<1|1].rsum; t[rt].ln=t[rt<<1].ln; t[rt].rn=t[rt<<1|1].rn; t[rt].msum=max(t[rt<<1].msum,t[rt<<1|1].msum); int ll=t[rt<<1].r-t[rt<<1].l+1; int rr=t[rt<<1|1].r-t[rt<<1|1].l+1; if(t[rt<<1].rn<t[rt<<1|1].ln) { if(t[rt<<1].lsum==ll) t[rt].lsum+=t[rt<<1|1].lsum; if(t[rt<<1|1].rsum==rr) t[rt].rsum+=t[rt<<1].rsum; t[rt].msum=max(t[rt].msum,t[rt<<1].rsum+t[rt<<1|1].lsum); } } void build(int l,int r,int rt) { t[rt].l=l; t[rt].r=r; if(l==r) { t[rt].ln=t[rt].rn=a[l]; t[rt].lsum=t[rt].rsum=t[rt].msum=1; return; } int m=t[rt].mid(); build(l,m,rt<<1); build(m+1,r,rt<<1|1); pushup(rt); } void update(int rt,int pos,int c) { if(t[rt].l==t[rt].r) { t[rt].ln=t[rt].rn=c; return; } int m=t[rt].mid(); if(pos<=m) update(rt<<1,pos,c); else update(rt<<1|1,pos,c); pushup(rt); } int query(int rt,int L,int R) { if(t[rt].l==L && t[rt].r==R) { return t[rt].msum; } int m=t[rt].mid(); if(R<=m) return query(rt<<1,L,R); else if(L>m) return query(rt<<1|1,L,R); else { int sum=0,m=t[rt].mid(); int ltmp=query(rt<<1,L,m); int rtmp=query(rt<<1|1,m+1,R); if(t[rt<<1].rn<t[rt<<1|1].ln) //注意:取最大值时要保证是在给定的区间[L,R]里面,左边,取min(全长,rsum),右边取min(全长,lsum) { sum=min(m-L+1,t[rt<<1].rsum)+min(R-m,t[rt<<1|1].lsum); } return max(max(ltmp,rtmp),sum); } } int main() { int T,n,m,i; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(i=0;i<n;i++) { scanf("%d",&a[i]); } build(0,n-1,1); while(m--) { char op; int a,b; scanf(" %c%d%d",&op,&a,&b); if(op==‘U‘) update(1,a,b); else if(op==‘Q‘) printf("%d\n",query(1,a,b)); } } return 0; }
原文:http://www.cnblogs.com/hate13/p/4119936.html