这题首先要倒着贴这样 每次➕就好了 还有就是 数据太大需要离散化
然后建线段树,根据x轴的坐标建坐标轴 ,看 这个点的 max(y) 有多大 如果 y[i]> max(y) 产生 贡献 ans+=y[x]-max(x)
x轴同理
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000001
struct ac{
int x,y;
}b[maxn];
int a[maxn],lz[maxn],c[maxn];
int n,tot=1,t=1;
void updata(int x,int y,int l,int r,int va,int in){
if(x==l&&y==r){
c[in]=max(c[in],va);
lz[in]=max(lz[in],va);
return ;
}
int mid=(l+r)/2;
if(lz[in]){
c[in*2]=max(lz[in],c[in*2]);
c[in*2+1]=max(lz[in],c[in*2+1]);
lz[in*2]=max(lz[in],lz[in*2]);
lz[in*2+1]=max(lz[in],lz[in*2+1]);
lz[in]=0;
}
if(x>mid){
updata(x,y,mid+1,r,va,in*2+1);
}else if(y<=mid){
updata(x,y,l,mid,va,in*2);
}else{
updata(mid+1,y,mid+1,r,va,in*2+1);
updata(x,mid,l,mid,va,in*2);
}
c[in]=max(c[in*2],c[in*2+1]);
}
int query(int x,int l,int r,int in){
if(l==r){
return c[in];
}
int mid=(l+r)/2;
if(lz[in]){
c[in*2]=max(lz[in],c[in*2]);
c[in*2+1]=max(lz[in],c[in*2+1]);
lz[in*2]=max(lz[in],lz[in*2]);
lz[in*2+1]=max(lz[in],lz[in*2+1]);
lz[in]=0;
}
if(x>mid){
return query(x,mid+1,r,in*2+1);
}
return query(x,l,mid,in*2);
}
int main(){
cin>>n;
for(int j=1;j<=n;j++){
cin>>b[j].x>>b[j].y;
a[tot++]=b[j].x;
a[tot++]=b[j].y;
}
sort(a+1,a+tot);
for(int i=2;i<tot;i++)if(a[i]!=a[i-1])a[++t]=a[i];
long long ans=0;
memset(c,0,sizeof(c));
memset(lz,0,sizeof(lz));
int l=lower_bound(a+1,a+t+1,b[n].x)-a;
int r=lower_bound(a+1,a+t+1,b[n].y)-a;
ans+=a[r]+a[l];
//cout<<ans<<endl;
updata(1,l,1,t,r,1); // 把 1-x 全部更新成 y 的最大值(离散化之后是坐标)
for(int j=n-1;j>=1;j--){
int l=lower_bound(a+1,a+t+1,b[j].x)-a;
int r=lower_bound(a+1,a+t+1,b[j].y)-a;
int i=query(l,1,t,1);
if(i<r){
ans+=a[r]-a[i];
}
int ll=1,rr=l;
int mi=1e9;
while(ll<=rr){ //我们要找比y小的最小的x 这样才会有贡献
int mid=(ll+rr)/2;
i=query(mid,1,t,1);
if(i<r){
mi=min(mi,mid); // 说明这个点的mid这个点的y < 当前j 点的y 可以产生贡献取min(x)
rr=mid-1;
}else ll=mid+1;
}
if(mi!=1e9){
ans+=a[l]-a[ll-1];
}
updata(1,l,1,t,r,1);
}
cout<<ans<<endl;
}