查询某个区间内连续出现次数最多的一个数出现的次数
以前做的时候,没有记录左边连续最多的次数,右边连续最多的次数,而是记录了出现最多的数的值,写的很长,还不知道WA哪了
前两天经队友点拨,发现对于这种求最长连续区间的问题,记录左边连续最多的次数(lv),右边连续最多的次数(rv),以及整个区间连续最多次数(val),更新和查询的时候会很方便
首先,如果左子区间的lv等于左子区间的长度且可以延伸到右子区间,那么父区间的lv值等于左子区间的lv加上右子区间的lv,否则,父区间的lv值就是左子区间的lv值,对于右子区间,同理
对于父区间的val值,应该是先在左右子区间的val值中取一个较大值,另外,如果左右区间能够延续,则在当前值和左子区间的rv+右子区间的lv之间取较大值
还有一个特殊情况就是在查询的时候,如果要分别在左子区间和右子区间查找,结果分别为x,y,如果左右两个区间不能延续,那肯定是在x,y中找一个最大值,如果可以延续的话,设延续部分的最大次数为z,那么,就要在x,y,z中取一个最大值,另外,求z时要比较小心,这个区间的左端点要在向左延伸的最远点和查询区间的左端点中取一个较大值,这个区间的有端点要在向右延伸的最远点和查询区间的有端点间取一个较小值,详情见代码
代码:
#include<iostream> #include<memory.h> #include<string> #include<cstdio> #include<algorithm> #include<math.h> #include<stack> #include<queue> using namespace std; const int MAX=120005; struct node { int l,r,lv,rv,val,len; }t[MAX*5]; int a[MAX]; void build(int ll,int rr,int n) { t[n].l=ll; t[n].r=rr; t[n].len=t[n].r-t[n].l+1; if(ll==rr) { t[n].lv=1;t[n].rv=1;t[n].val=1; return ; } int mid=(t[n].l+t[n].r)/2; build(ll,mid,n*2); build(mid+1,rr,n*2+1); if(t[n*2].lv==t[n*2].len&&a[t[n*2].r]==a[t[n*2+1].l]) t[n].lv=t[n*2].lv+t[n*2+1].lv; else t[n].lv=t[n*2].lv; if(t[n*2+1].rv==t[n*2+1].len&&a[t[n*2].r]==a[t[n*2+1].l]) t[n].rv=t[n*2].rv+t[n*2+1].rv; else t[n].rv=t[n*2+1].rv; if(a[t[n*2].r]==a[t[n*2+1].l]) { t[n].val=t[n*2].rv+t[n*2+1].lv; t[n].val=max(t[n].val,max(t[n*2].val,t[n*2+1].val)); } else t[n].val=max(t[n*2].val,t[n*2+1].val); } int query(int ll,int rr,int n) { if(t[n].l==ll&&t[n].r==rr) return t[n].val; int mid=(t[n].l+t[n].r)/2; if(mid>=rr) return query(ll,rr,n*2); else if(mid<ll) return query(ll,rr,n*2+1); else { int x=query(ll,mid,n*2); int y=query(mid+1,rr,n*2+1); int z; //cout<<"x="<<x<<" y="<<y<<endl; if(a[t[n*2].r]==a[t[n*2+1].l]) { z=rr-ll+1; z=min(z,min(rr,t[n*2+1].l+t[n*2+1].lv-1)-max(t[n*2].r-t[n*2].rv+1,ll)+1); //左边界取较大值,右边界取较小值 //cout<<"z="<<z<<endl; return max(z,max(x,y)); } else return max(x,y); } } int main() { int n,m,i,j; while(scanf("%d",&n)!=EOF&&n) { scanf("%d",&m); for(i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); while(m--) { scanf("%d%d",&i,&j); printf("%d/n",query(i,j,1)); } } return 0; }