1. 程式人生 > 其它 >洛谷P1496 火燒赤壁 (模擬/離散化+差分)

洛谷P1496 火燒赤壁 (模擬/離散化+差分)

分析可知:將起點和終點按照從小到大的順序排序,對答案不會產生影響

所以此時我們得到一種模擬做法:

 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;
 3
const 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)段無用

因為排序後對答案沒有影響,所以這種方法是正確的。