本番意外に苦戦してるな…。
https://atcoder.jp/contests/arc076/tasks/arc076_d
問題
座標1~Mの格子点それぞれにイスが1つずつある。
ここにN人の人がいる。
i番目の人は1~L[i]またはR[i]~Mの間のイスにしか座りたくない。
全員をイスに座らせるには、最大何個イスを追加すればよいか。
解法
M個のイスに最大何人人を座らせられるかを求めればよい。
一見区間スケジューリングの問題に近いが、人の座る範囲が2つに分かれているのがやりにくい。
ただ、1~Mの座標を直線とみなすのではなく、円環状になっていると考えよう。
そうすると結局各人は円環状のある1つの区間に座りたいことになる。
そこで円環状を2~3周しながら区間スケジューリング(座標順に見て、座れる位置が手前の人ほど優先して座らせる)を行い、1周の間で最大何人すわれるかを求めればよい。
int N,M; vector<int> ev[602020]; int did[602020]; void solve() { int i,j,k,l,r,x,y; string s; int ret=0; cin>>N>>M; FOR(i,N) { cin>>x>>y; x+=M; ev[y].push_back(x); ev[y+M].push_back(x+M); } multiset<int> ed; int ma=0; FOR(i,3*M) { FORR(e,ev[i]) ed.insert(e); while(ed.size() && *ed.begin()<i) ed.erase(ed.begin()); if(i) did[i]=did[i-1]; if(ed.size()) { did[i]++; ed.erase(ed.begin()); } if(i>M) ma=max(ma,did[i]-did[i-M]); } cout<<N-ma<<endl; }
まとめ
数直線の両端をくっつけることに気が付けばあとは簡単。