--- title: Codeforce 1237C2 description: "Codeforce 1237C2 geometry" --- <!-- toc --> # Codeforce 1237C2 Balanced Removals (Harder) (幾何、思維) 今天我們來看看CF1237C2 [題目連結](https://codeforces.com/problemset/problem/1237/C2) > **題目** 給你偶數個三維座標點,每次選其中兩點,如果兩點為對角的盒子(可以退化成2,1維)中不包含其他未移除的點,那麼就可以把這兩點移除。要輸出一個合法的移除順序 ### 想法 如果現在只有一維,那麼問題就簡單了,把座標排序一下,兩個兩個移除就好。 所以我們如果能夠把問題化約到一維上就解決了。 觀察到,如果現在有n個(不保證偶數)一維的點,那麼刪除到最後會最多剩下一個點。利用這點,首先我們把同樣z座標的點分堆收集起來(圖形上來看:把在同樣x-y平面的點收集起來),然後接著遞迴地處理: 對於每個x-y平面,把同樣y座標的點收集起來(圖形上來看:把在同樣x軸直線的點收集起來)...。 而每個降一個維度的點集處理完以後,有可能會有剩餘一個點無法處理,把這些點收集起來就會是一個一維的點集,就可以直接兩個兩個輸出了。 ### 程式碼: ```c++ 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](https://codeforces.com/contest/1237/submission/90325824)