Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
线段树区间合并...开始傻傻的不断查 后来发现有一种情况可以算出来...#include<iostream> #include<cstdio> #include<cstring> #define maxn 100010 #define lc (k<<1) #define rc (k<<1)+1 #define mid ((l+r)>>1) using namespace std; int n,m,a[maxn],ls[maxn*4],rs[maxn*4],ln[maxn*4],rn[maxn*4],s[maxn*4]; int init(){ int x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } void Build(int k,int l,int r){ if(l!=r){ Build(lc,l,mid); Build(rc,mid+1,r); s[k]=max(s[lc],s[rc]); if(rn[lc]==ln[rc]) s[k]=max(s[k],rs[lc]+ls[rc]); ln[k]=ln[lc];rn[k]=rn[rc]; ls[k]=ls[lc];rs[k]=rs[rc]; if(ls[lc]==mid-l+1&&rn[lc]==ln[rc]) ls[k]=max(ls[k],ls[lc]+ls[rc]); if(rs[rc]==r-mid&&rn[lc]==ln[rc]) rs[k]=max(rs[k],rs[rc]+rs[lc]); } else{ ls[k]=rs[k]=1;ln[k]=rn[k]=a[l];s[k]=1; } } int Query(int k,int l,int r,int x,int y){ if(x<=l&&y>=r)return s[k]; int ret=0,L,R; if(y<=mid)return Query(lc,l,mid,x,y); else if(x>mid)return Query(rc,mid+1,r,x,y); else{ if(rn[lc]==ln[rc]){ L=max(mid-rs[lc]+1,x); R=min(mid+ls[rc],y); ret=mid-L+1+R-mid; } //ret=Query(lc,l,mid,max(mid-rs[lc]+1,x),mid) //+Query(rc,mid+1,r,mid+1,min(mid+ls[rc],y));可以只结算出来 ret=max(ret,Query(lc,l,mid,x,y)); ret=max(ret,Query(rc,mid+1,r,x,y)); } return ret; } int main() { while(1){ n=init();if(n==0)break; m=init(); for(int i=1;i<=n;i++)a[i]=init(); Build(1,1,n); while(m--){ int L,R; L=init();R=init(); printf("%d\n",Query(1,1,n,L,R)); } } return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator