POJ 3368 RMQ 找區間段出現次數最多的數
阿新 • • 發佈:2018-11-11
給出一個非降序排列的整數陣列a1,a2,...an,你的任務是對於一系列詢問(i, j),回答ai,ai+1,...aj中出現最多次數的值所出現的次數?
<span style="font-size:18px;">#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN =200000+1000; int dmax[MAXN][20]; int a[MAXN]; int left[MAXN],right[MAXN],num[MAXN]; int d[MAXN];//d[i]=8表第i個不同的值出現了8次 void initmax(int n,int d[]) { for(int i=1;i<=n;i++) dmax[i][0]=d[i]; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++) dmax[i][j]=max( dmax[i][j-1],dmax[i+(1<<(j-1))][j-1] ); } int getmax(int L,int R) { int k=0; while(1<<(k+1)<=R-L+1)k++; return max(dmax[L][k],dmax[R+1-(1<<k)][k]); } int main() { int n,q; while(scanf("%d",&n)==1&&n) { memset(d,0,sizeof(d)); scanf("%d",&q); scanf("%d",&a[1]); int cnt=1;//表示當前出現了多少個不同的值 left[cnt]=1;//第cnt段最左邊是位置1 right[cnt]=1;//第cnt段最右邊是位置1 num[1]=cnt;//第一個元素屬於第cnt段 d[cnt]=1;//第cnt段目前有1個元素 for(int i=2;i<=n;i++) { scanf("%d",&a[i]); if(a[i]==a[i-1]) { num[i]=cnt; right[cnt]=i; d[cnt]++; } else//出現新值 { num[i]=++cnt; left[cnt]=i; right[cnt]=i; d[cnt]=1; } } initmax(n,d);//注意 while(q--) { int L,R; scanf("%d%d",&L,&R); int num_L=num[L],num_R=num[R]; if(num_L==num_R) printf("%d\n",R-L+1); else { int temp1=right[num[L]]-L+1;//a[L]出現的次數 int temp2=R-left[num[R]]+1;//a[R]出現的次數 int temp3=0; if(num_R-num_L>1) temp3 = getmax(num_L+1,num_R-1); int ans = max(temp3,max(temp1,temp2)); printf("%d\n",ans); } } } return 0; } </span>