Codeforces 45 C. Dancing Lessons
問題
男女n人が一列に並んでいる。
それぞれの性別およびスキルの値が与えられる。
この列に対して、以下のような方法でペアを作れるだけ作る。
- 列で隣り合う男女のうち、スキルの差の絶対値が最も小さいペア(複数ある場合最も左のペア)を選び、ペアを作る。二人は列から外す。
このとき、出来るペアを順に出力せよ。
制約条件
n≦2*10^5
方針
両隣の人を覚えておく。
ペアが作られるたびにその部分だけ関係を更新する。
隣合うペアのうちのスキルの差が最小のものを選ぶため、
差をpriority_queueに入れられれば良いのであるが、
ペアを一組(たとえばa,bを)選ぶと、priority_queueからaまたはbを片方として含むペアを取り除く操作が必要であるため、
stlのpriority_queueをそのまま使うことは出来ない。
priority_queueの代わりにsetを使えば、要素の削除および最小値の取り出しがO(log n)時間で出来る。
ソースコード
int n,s[200001]; char g[200001]; set<pair<int,pi> > S; vector<pi> ans; int l[200001],r[200001]; void run(){ cin>>n>>g; rep(i,n){ cin>>s[i]; l[i]=r[i]=-1; } S.clear(); ans.clear(); rep(i,n-1){ if(g[i]!=g[i+1])S.insert(mp(abs(s[i]-s[i+1]),mp(i,i+1))); r[i]=i+1; l[i+1]=i; } while(!S.empty()){ int a=(*S.begin()).second.first, b=(*S.begin()).second.second; int aa=l[a], bb=r[b]; S.erase(S.begin()); ans.push_back(mp(a+1,b+1)); if(aa>=0){ S.erase(mp(abs(s[a]-s[aa]),mp(aa,a))); r[aa]=bb; } if(bb>=0){ S.erase(mp(abs(s[b]-s[bb]),mp(b,bb))); l[bb]=aa; } if(aa>=0&&bb>=0&&g[aa]!=g[bb])S.insert(mp(abs(s[aa]-s[bb]),mp(aa,bb))); } cout<<ans.size()<<endl; rep(i,ans.size())cout<<ans[i].first<<" "<<ans[i].second<<endl; }