传送门: http://acm.pku.edu.cn/JudgeOnline/problem?id=3368 本题难点在于求取两个相邻区间的最长子串。 #include<iostream> using namespace std; #define M 100005 struct D{int l,r,m;}; int A[M],B[M];//A[i]表示i位开始有多少位相同;B[i]表示前面有多少相同 int C[M]; D L[M*3]; int n;//length int sum; void init() { int i; A[n]=1; B[1]=1; for(i=n-1;i>0;i--) { if(C[i]==C[i+1]) A[i]=A[i+1]+1; else A[i]=1; } for(i=2;i<=n;i++) { if(C[i]==C[i-1]) B[i]=B[i-1]+1; else B[i]=1; } } void create(int pos,int lt,int rt){ L[pos].l=lt; L[pos].r=rt; if(lt==rt) { L[pos].m=1; return; } int mid=(lt+rt)/2; create(pos*2,lt,mid); create(pos*2+1,mid+1,rt); L[pos].m=max(L[pos*2].m,L[pos*2+1].m); if(C[L[pos*2].r]==C[L[pos*2+1].l]) { int a=min(B[L[pos*2].r],L[pos*2].r-L[pos*2].l+1); int b=min(A[L[pos*2+1].l],L[pos*2+1].r-L[pos*2+1].l+1); L[pos].m=max(L[pos].m,a+b); } } int search(int pos,int lt,int rt) { if(lt>rt) return 0; if(lt==L[pos].l&&rt==L[pos].r) { return L[pos].m; } int mid=(L[pos].l+L[pos].r)/2; if(rt<=mid) return search(pos*2,lt,rt); else if(lt>=mid+1) return search(pos*2+1,lt,rt); else{ int aa=search(pos*2,lt,mid); int bb=search(pos*2+1,mid+1,rt); aa=max(aa,bb); if(C[L[pos*2].r]==C[L[pos*2+1].l]) { int a=min(B[L[pos*2].r],L[pos*2].r-lt+1); int b=min(A[L[pos*2+1].l],rt-L[pos*2+1].l+1); aa=max(aa,a+b); } return aa; } } int main() { int i,a,b; while(scanf("%d",&n)!=EOF,n) { int q; scanf("%d",&q); for(int i=1;i<=n;i++) scanf("%d",&C[i]); init(); create(1,1,n); for(i=1;i<=q;i++) {scanf("%d%d",&a,&b);; printf("%d/n",search(1,a,b)); } } }