C2. Balanced Removals (Harder) (幾何、思維)

Codeforce 1237C2 Balanced Removals (Harder) (幾何、思維)

今天我們來看看CF1237C2
題目連結

題目
給你偶數個三維座標點,每次選其中兩點,如果兩點為對角的盒子(可以退化成2,1維)中不包含其他未移除的點,那麼就可以把這兩點移除。要輸出一個合法的移除順序

想法

如果現在只有一維,那麼問題就簡單了,把座標排序一下,兩個兩個移除就好。
所以我們如果能夠把問題化約到一維上就解決了。
觀察到,如果現在有n個(不保證偶數)一維的點,那麼刪除到最後會最多剩下一個點。利用這點,首先我們把同樣z座標的點分堆收集起來(圖形上來看:把在同樣x-y平面的點收集起來),然後接著遞迴地處理:
對於每個x-y平面,把同樣y座標的點收集起來(圖形上來看:把在同樣x軸直線的點收集起來)...。
而每個降一個維度的點集處理完以後,有可能會有剩餘一個點無法處理,把這些點收集起來就會是一個一維的點集,就可以直接兩個兩個輸出了。

程式碼:

const int _n=5e4+10;
int t,n;
vector<VI> p(_n,VI(3));
int solve(VI& ids,int d){
  if(d==0)return ids[0];
  map<int,VI> mp;
  rep(i,0,SZ(ids))mp[p[ids[i]][d-1]].pb(ids[i]);
  VI left;
  for(auto& x:mp){
    int res=solve(x.se,d-1);
    if(res!=-1)left.pb(res);
  }
  for(int i=0;i+1<SZ(left);i+=2){cout<<left[i]+1<<' '<<left[i+1]+1<<'\n';}
  if(SZ(left)%2==1)return left.back();
  return -1;
}
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,0,n)rep(j,0,3)cin>>p[i][j];
  VI init;rep(i,0,n)init.pb(i);
  solve(init,3);
  return 0;
}

標頭、模板請點Submission看
Submission

posted @ 2020-08-22 19:40  petjelinux  阅读(93)  评论(0编辑  收藏  举报