UVA11235 Frequent values
阿新 • • 發佈:2018-11-02
連結的話是沒有的,我是拿的洛咕的remote judge交的。
做之前一定要讀好題面。
注意到是非減的。便由此可以,可以將連續的一段(or 一個)數字,壓成一個數字。
然後再在上面處理問題。差不多類似分了個塊吧。
然後這樣的話,我們便只需要跑rmq就可以了。
對於塊內,直接左右鑲件。對於塊見,使用資料結構維護,
然後因為是靜態rmq,所以使用st表就比較優了。
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> using std::max; const int maxn=101000; int base[maxn]; int log[maxn]; int belong[maxn],id; int l[maxn],r[maxn]; int st[maxn][22]; void init(int n) { id=0; int now=-0x7fffffff; l[0]=0,id=0;base[n+1]=0x7fffffff; for(int i=1;i<=n+1;i++) { if(base[i]!=now) { r[id++]=i-1; l[id]=i; now=base[i]; } belong[i]=id; } for(int i=1;i<id;i++) st[i][0]=r[i]-l[i]+1; for(int i=1;i<=log[id-1];i++) for(int j=1;j+(1<<i)-1<id;j++) st[j][i]=max(st[j][i-1],st[j+(1<<i-1)][i-1]); return ; } int check(int L,int R) { if(L>R) return 0; if(L==R) return r[L]-l[R]+1; int len=log[R-L+1]; return max(st[L][len],st[R-(1<<len)+1][len]); } int main() { for(int i=2;i<maxn;i++) log[i]=log[i>>1]+1; int n,q; scanf("%d",&n); while(n) { scanf("%d",&q); for(int i=1;i<=n;i++) scanf("%d",&base[i]); init(n); int a,b; for(int i=1;i<=q;i++) { scanf("%d%d",&a,&b); if(belong[a]==belong[b]) printf("%d\n",b-a+1); else { int ans=check(belong[a]+1,belong[b]-1); ans=max(ans,max(r[belong[a]]-a+1,b-l[belong[b]]+1)); printf("%d\n",ans); } } scanf("%d",&n); } }