# ZeroJudge f607: 3. 切割費用 [f607: 3. 切割費用](https://zerojudge.tw/ShowProblem?problemid=f607) ###### tags: `Discretization` `DSU` ### 題目敘述: 給定N個切點座標和順序,每次裁切的成本為當前線段長度,輸出過程當中的成本總和? ### 題目盲點:BinarySearchTree worst-case * 依照題目給予的"規則"根據順序模擬切點,並找到該線段左右端點做累加 ... O(n^2)。 * 需要知道已經存在的切點當中 最大且小於 cut[i] 的座標和最小且大於 cut[i] 的座標,之後將該節點加入切點的集合中。 ### 解題關鍵: Discretization + DSU * 離散化處理切點座標 * 照順序的切點=反順序的連接,DSU尋找當下切點的左右端點 * 計算完後將該節點右 root 指向右側端點的 root,左 root 指向左側端點的 root ``` cpp #include<bits/stdc++.h> using namespace std; const int MaxN=2e5; const int MaxL=1e7; int cut[MaxN+2]; int pos[MaxN+2]; int Lrt[MaxN+2]; int Rrt[MaxN+2]; int FindRoot(int x,int* root){ return (root[x]==x)? x: root[x]=FindRoot(root[x],root); } int main(){ int N, L, p, o; scanf("%d %d\n",&N,&L); for(int i=1;i<=N;i++){ scanf("%d %d\n",&p,&o); pos[i]=cut[o]=p; Lrt[i]=Rrt[i]=i; // init for DSU } sort(pos+1,pos+N+1); // for Discretization pos[0]=0; Lrt[0]=Rrt[0]=0; pos[N+1]=L; Lrt[N+1]=Rrt[N+1]=N+1; long ansL=0; for(int i=N; i>0; i--){ p=lower_bound(pos,pos+N+1,cut[i])-pos; // 離散化 int toL=FindRoot(p-1,Lrt); // 找到目前節點"左側" int toR=FindRoot(p+1,Rrt); // 找到目前節點"右側" // 計算「因為這個節點存在前」的左右邊界,轉換為離散化前的真實座標 ansL+= pos[toR]-pos[toL]; Lrt[p]=toL; // 將目前節點連接給他左端點的"root" Rrt[p]=toR; // 將目前節點連接給他右端點的"root" } printf("%d\n",ansL); } ```