題意:n個左下角爲原點右上角在第一象限的矩形不斷覆蓋,求最後造成的圖形的周長c++
x和y是獨立的,分別維護兩棵線段樹,一棵表示x座標下最大的y值,另外一棵表示y座標下最大的x值spa
從覆蓋的角度來考慮,若是逆序處理,當前處理的段的貢獻爲大於等於當前位置的最大值的差code
好比一條橫的線段i,座標爲[x1=0,x2],y
那它對答案的貢獻爲max(0,x2 - max_x of [y,maxy]),此時的區間存在的線段爲逆序第n條到第i+1條ci
處理完後再插入到對應的線段樹中便可(其實貢獻爲0的不插也行,由於都是不斷取一個後綴最大的值)get
#include<bits/stdc++.h> #define rep(i,j,k) for(int i=j;i<=k;i++) #define rrep(i,j,k) for(int i=j;i>=k;i--) #define println(a) printf("%lld\n",(ll)(a)) #define printbk(a) printf("%lld ",(ll)(a)) typedef long long ll; using namespace std; const int MAXN = 2e5+11; const ll oo = 0x3f3f3f3f3f3f3f3f; const ll ooo= 0x3f3f3f3f; const int MOD = 1e9+7; ll read(){ ll x=0,f=1;register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct ST{ #define lc o<<1 #define rc o<<1|1 ll mx[MAXN<<2]; void pu(int o){ mx[o]=max(mx[lc],mx[rc]); } void update(int o,int l,int r,int k,ll v){ if(l==r){ mx[o]=max(mx[o],v); return; } int mid=l+r>>1; if(k<=mid) update(lc,l,mid,k,v); else update(rc,mid+1,r,k,v); pu(o); } ll query(int o,int l,int r,int L,int R){ if(L<=l&&r<=R) return mx[o]; int mid=l+r>>1; ll ans=0; if(L<=mid) ans=max(ans,query(lc,l,mid,L,R)); if(R>mid) ans=max(ans,query(rc,mid+1,r,L,R)); return ans; } }st[2]; struct QAQ{ int x, y; int _x,_y; QAQ(int Q=0,int A=0){ x=Q; y=A; } }a[MAXN]; int xx[MAXN],yy[MAXN],n; int main(){ while(cin>>n){ int cnt=0; rep(i,1,n){ int x=read(); int y=read(); a[i]=QAQ(x,y); xx[++cnt]=x; yy[cnt]=y; } sort(xx+1,xx+1+cnt); sort(yy+1,yy+1+cnt); rep(i,1,n){ a[i]._x=lower_bound(xx+1,xx+1+cnt,a[i].x)-xx; a[i]._y=lower_bound(yy+1,yy+1+cnt,a[i].y)-yy; } rep(i,0,1) memset(st[i].mx,0,sizeof st[i].mx); //st[0]: x座標下最大的y //st[1]: y座標下最大的x ll ans=0; rrep(i,n,1){ int x=a[i].x; int y=a[i].y; int xid=a[i]._x; int yid=a[i]._y; ll t1=st[1].query(1,1,cnt,yid,cnt); if(t1<x) ans+=x-t1; st[1].update(1,1,cnt,yid,x); ll t2=st[0].query(1,1,cnt,xid,cnt); if(t2<y) ans+=y-t2; st[0].update(1,1,cnt,xid,y); } println(ans); } return 0; }