Codeforces 76 B. Mice

問題

n匹のネズミがy=y0の直線上に一列に並んでいる。
m個のチーズがy=y1の直線上に一列に並んでいる。


それぞれのネズミおよびチーズの座標が与えられる。
ネズミは次のように動く。

  • 最も近いチーズに向けて走る。
  • チーズに最初に辿り着いたネズミは、それを食べておなか一杯になる。
  • 複数のネズミが同時に一つのチーズに辿り着いたら、分け合って全部のネズミがおなか一杯になることができる。
  • 最も近いチーズが複数あるネズミは、おなか一杯になるネズミの数が最大になるようにチーズを選ぶ。

このとき、おなか一杯にならないネズミの数を求めよ。

方針

貪欲法による。
TopCoderでも出たことがある、辺に交差がなくて、次数が最大2の二部グラフ。


ネズミを順に見ていき、一つしかチーズがないのなら、そのチーズにネズミを割り当てる。
二つ狙えるチーズがあったら、左に共有できるチーズがあったら、左に向かわせる。
そうでないなら右のチーズに割り当てる。

を繰り返す貪欲法により解ける。

ソースコード

int n,m;
int used[100000];

void run()
{
	scanf("%d%d",&n,&m);
	int y1,y2; scanf("%d%d",&y1,&y2);
	vi mouse,cheese;
	
	rep(i,n){
		int x; scanf("%d",&x);
		mouse.pb(x);
	}
	rep(i,m){
		int x; scanf("%d",&x);
		cheese.pb(x);
	}
	memset(used,-1,sizeof(used));
	int i=0,j=0,ans=n;
	
	for(;i<n&&j<m;i++){
		while(j<m-1&&abs(mouse[i]-cheese[j+1])<abs(mouse[i]-cheese[j]))j++;
		if(used[j]==-1||used[j]==abs(mouse[i]-cheese[j])){
			used[j]=abs(mouse[i]-cheese[j]);
			ans--;
			continue;
		}
		if(j<m-1&&abs(mouse[i]-cheese[j+1])==abs(mouse[i]-cheese[j])){
			if(used[j]==abs(mouse[i]-cheese[j]))ans--;
			else{
				used[j+1]=abs(mouse[i]-cheese[j]);
				ans--;
			}
		}
		else{
			used[j]=abs(mouse[i]-cheese[j]);
		}
	}
	
	printf("%d\n",ans);
}