分析
我们可以发现,对于一个区间[l,r],l左侧想要去到r右侧的有a个,r右侧想要去到l左侧的有b个,那么这个区间将要被经过(r-l+1)*(2*a-1)次或(r-l+1)*(2*b+1)次
为什么是“或”而不是“和”呢?我们发现当a>b时,我们每次把a中的一个运过去时,可以顺便把b的一个带过来,所以只用做(r-l+1)*(2*a-1)次,同理b>a也差不多
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; const int N=1e5+10; int a[2*N],s[N][2]; int cnt; int n,m; ll ans,L[2*N],R[2*N]; int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d%d",&s[i][0],&s[i][1]); a[++cnt]=s[i][0],a[++cnt]=s[i][1]; } sort(a+1,a+cnt+1); cnt=unique(a+1,a+cnt+1)-(a+1); for (int i=1;i<=n;i++) { int l=lower_bound(a+1,a+cnt+1,s[i][0])-a,r=lower_bound(a+1,a+cnt+1,s[i][1])-a; if (l<r) L[l]++,L[r]--; else R[l]++,R[r]--; } for (int i=1;i<=cnt;i++) L[i]+=L[i-1]; for (int i=cnt;i>=1;i--) R[i]+=R[i+1]; ans=m-(a[cnt]-a[1]); for (int i=2;i<=cnt;i++) { int l=L[i-1],r=R[i]; if (l>r) ans+=1ll*(2*l-1)*(a[i]-a[i-1]); else ans+=1ll*(2*r+1)*(a[i]-a[i-1]); } printf("%lld",ans); }