PKU 3368 Frequent values
http://poj.org/problem?id=3368
ソートされた数列が与えられる。
範囲iからjで最も出現回数の多い数字の出現個数を求めろというような問題。
レンジクエリー(というのでしょうか?これもRMQ?)。
ある範囲の中で、その左端から連続する数列の個数と値
右端から連続する数列の個数と値
真ん中で連続する数が最大の個数と値
を処理していく感じで実装しました。
まずinsert関数、query関数を書くのに大分時間がかかり、TLEと戦うのにも大分時間がかかりました。
結局merge関数を出来るだけ早くして何とか通しました。
char input[18167830]; int pos; char c; int gret; int getnum(){ while(!isdigit(c=input[pos++])) if(c=='-')return -getnum(); gret=c&15; while(isdigit(c=input[pos++]))gret=(gret<<3)+(gret<<1)+(c&15); return gret; } typedef struct{ int rs[3]; int re[3]; int v[3]; }node; int n_,n; node arr[1000000]; node empty; void pr(const node& in){ rep(i,3){ cout<<' '<<in.rs[i]<<' '<<in.re[i]<<' '<<in.v[i]<<endl; } } node merge(const node& le,const node& ri){ if(le.re[0]==0)return ri; if(ri.re[0]==0)return le; node ret(le); rep(i,3){ if(ret.v[0]==ri.v[i])ret.re[0]=max(ret.re[0],ri.re[i]); } if(ret.v[2]!=ri.v[2]){ ret.rs[2]=ri.rs[2]; ret.re[2]=ri.re[2]; ret.v[2]=ri.v[2]; }else ret.re[2]=ri.re[2]; if(ret.re[1]-ret.rs[1]<ri.re[1]-ri.rs[1]){ ret.re[1]=ri.re[1]; ret.rs[1]=ri.rs[1]; ret.v[1]=ri.v[1]; } if(ret.re[1]-ret.rs[1]<ret.re[2]-ret.rs[2]){ ret.re[1]=ret.re[2]; ret.rs[1]=ret.rs[2]; ret.v[1]=ret.v[2]; } if(le.v[2]==ri.v[0] && ret.re[1]-ret.rs[1]<ri.re[0]-le.rs[2]){ ret.rs[1]=le.rs[2]; ret.re[1]=ri.re[0]; ret.v[1]=le.v[2]; } return ret; } void insert(int pos,int x){ node v; rep(i,3){ v.rs[i]=pos; v.re[i]=pos+1; v.v[i]=x; } pos+=n_; arr[pos]=v; do{ pos=(pos-1)/2; v=arr[pos]=merge(arr[pos],v); }while(pos); } node query(int qs,int qe,int as,int ae,int k){ if(ae<=qs || qe<=as)return empty; if(qs<=as && ae<=qe)return arr[k]; return merge(query(qs,qe,as,(as+ae)/2,k*2+1),query(qs,qe,(as+ae)/2,ae,k*2+2)); } int nmax(const node &in){ int ret(in.re[2]-in.rs[2]); rep(i,2){ ret=max(ret,in.re[i]-in.rs[i]); } return ret; } void solve(){ int q(getnum()); n_=1; while(n_<n)n_<<=1; --n_; memset(arr,0,sizeof(arr)); rep(i,n){ insert(i,getnum()); } rep(i,q){ int s(getnum()); int e(getnum()); printf("%d\n",nmax(query(s-1,e,0,n_+1,0))); } } main(){ fread(input,sizeof(input),1,stdin); while(n=getnum())solve(); }