求一段非递减序列出现频率最高的数字的个数,线段树做的,每个节点记录5个信息
lv:区间最左边的数字,rv:区间最右边的数字
ml:与区间最左边的数字相等的数字的个数,mr:与区间最右边的数字相等的数字的个数
maxv:区间中出现频率最高的数字的个数,然后通过线段树查询即可
以后看到与区间信息有关的题目要想到用线段树
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 const int maxn=100000+10; 5 struct node 6 { 7 int ml,mr,maxv,lv,rv; 8 }; 9 node sgtree[maxn*3]; 10 int a[maxn]; 11 int n,q,tot,k; 12 int ql,qr; 13 void Init(int no,int l,int r) 14 { 15 if(l==r) 16 { 17 sgtree[no].maxv=1; 18 sgtree[no].ml=1; 19 sgtree[no].mr=1; 20 sgtree[no].lv=a[tot]; 21 sgtree[no].rv=a[tot++]; 22 return; 23 } 24 int mid=l+(r-l)/2; 25 int tl=no*2+1,tr=no*2+2; 26 Init(tl,l,mid); 27 Init(tr,mid+1,r); 28 sgtree[no].maxv=max(sgtree[tl].maxv,sgtree[tr].maxv); 29 if(sgtree[tl].rv==sgtree[tr].lv) 30 sgtree[no].maxv=max(sgtree[no].maxv,sgtree[tl].mr+sgtree[tr].ml); 31 sgtree[no].lv=sgtree[tl].lv; 32 sgtree[no].rv=sgtree[tr].rv; 33 sgtree[no].ml=sgtree[tl].ml; 34 sgtree[no].mr=sgtree[tr].mr; 35 if(sgtree[tl].lv==sgtree[tr].lv) sgtree[no].ml+=sgtree[tr].ml; 36 if(sgtree[tr].rv==sgtree[tl].rv) sgtree[no].mr+=sgtree[tl].mr; 37 } 38 int Query(int no,int l,int r) 39 { 40 int tl=no*2+1,tr=no*2+2; 41 if(l>=ql&&r<=qr) return sgtree[no].maxv; 42 int mid=l+(r-l)/2; 43 if(ql>mid) return Query(no*2+2,mid+1,r); 44 else if(qr<=mid) return Query(no*2+1,l,mid); 45 else 46 { 47 int t1=Query(tl,l,mid); 48 int t2=Query(tr,mid+1,r); 49 int ans=max(t1,t2); 50 if(sgtree[tl].rv==sgtree[tr].lv) 51 { 52 int a1=(mid-ql+1)>=sgtree[tl].mr?sgtree[tl].mr:(mid-ql+1); 53 int a2=(qr-mid)>=sgtree[tr].ml?sgtree[tr].ml:(qr-mid); 54 ans=max(ans,a1+a2); 55 } 56 return ans; 57 } 58 } 59 int main() 60 { 61 while(scanf("%d",&n)&&n) 62 { 63 scanf("%d",&k); 64 int i; 65 for(i=0;i<n;i++) scanf("%d",&a[i]); 66 tot=0; 67 Init(0,1,n); 68 int l,r; 69 int ans; 70 for(i=0;i<k;i++) 71 { 72 scanf("%d%d",&ql,&qr); 73 ans=Query(0,1,n); 74 printf("%d\n",ans); 75 } 76 } 77 return 0; 78 }