洛谷P1496 火燒赤壁 (模擬/離散化+差分)
阿新 • • 發佈:2022-04-16
分析可知:將起點和終點按照從小到大的順序排序,對答案不會產生影響
所以此時我們得到一種模擬做法:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2e4+10; 4 int n,a[N],b[N],ans; 5 //模擬做法 6 int main(){ 7 scanf("%d",&n); 8 for(int i=1;i<=n;i++) 9 scanf("%d%d",&a[i],&b[i]); 10 sort(a+1,a+n+1);sort(b+1,b+n+1); 11 for(int i=1;i<=n;i++){ 12 ans+=b[i]-a[i]; 13 if(i!=n)//不是最後一條線段 14 if(b[i]>a[i+1]) ans-=b[i]-a[i+1];//減去重複的 15 } 16 cout<<ans; 17 }
注意可能會有重複的,要減去。
當然,我們還可以離散化(雖然說沒有必要):
1 #include<bits/stdc++.h> 2 using namespace std; 3const int N=2e4+10; 4 int n,ans,temp,cnt,a[N],b[N],x[2*N]; 5 int f[2*N];//判斷是否有效 6 //離散化 7 int main(){ 8 scanf("%d",&n); 9 for(int i=1;i<=n;i++){ 10 scanf("%d%d",&a[i],&b[i]); 11 x[++cnt]=a[i];x[++cnt]=b[i]; 12 } 13 sort(x+1,x+cnt+1); 14 cnt=unique(x+1,x+cnt+1)-x-1; 15 for(int i=1;i<=n;i++){ 16 a[i]=lower_bound(x+1,x+cnt+1,a[i])-x; 17 b[i]=lower_bound(x+1,x+cnt+1,b[i])-x; 18 f[a[i]]++;f[b[i]]--;//差分小優化 19 } 20 for(int i=1;i<=cnt;i++){ 21 temp+=f[i]; 22 if(temp) ans+=x[i+1]-x[i];//累加答案 23 } 24 cout<<ans; 25 }
什麼是有效?比如:
有兩對線段(x1,y1)(x2,y2) 如果x1>y2或x2>y1,那麼(y2,x1)段或(y1,x2)段無用
因為排序後對答案沒有影響,所以這種方法是正確的。