1. 程式人生 > >ACM-ICPC 2018 徐州賽區網路預賽 G. Trace (線段樹維護)

ACM-ICPC 2018 徐州賽區網路預賽 G. Trace (線段樹維護)

題意
你在海灘上有浪花,所有的浪花都是矩形的,當一個浪花來了之後,就會覆蓋他的前一個浪花,問你最後浪花的周長和
思路
我們從後往前來,這樣的話,我們處理的都是會留下來的,怎樣的會留下來呢?這裡寫圖片描述
首先我們先看1號點和2號點,由圖我們可以很明顯的看出1號點會被淹沒,而1`和1“他們不會被淹沒,所以對於我們當前的值來說,我們維護一下大於他的x的最大的y,和大於他的y座標的最大的x,這兩個值,然後每次查詢之後觀察我們當前的x[i],和y[i]的關係,加上貢獻就好,具體怎麼維護,我們把所有點離散下來,建兩顆線段樹,1顆以x的座標為線段樹的區間,y為線段樹的權值維護y的最大值,x座標反之,之後對於查詢*(x,y),我們查 (x,n)區間中的最大值,二維變一維了就。
程式碼

#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; } // for(int i = 1 ; i <= n ; i++) printf("%d %d\n",a[i]._x,a[i]._y); 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; }