1. 程式人生 > >【ACM-ICPC 2018 徐州賽區網路預賽 G. Trace】 離散化+權值線段樹

【ACM-ICPC 2018 徐州賽區網路預賽 G. Trace】 離散化+權值線段樹

題目連結 https://nanti.jisuanke.com/t/31459 題意 題意就是按順序給出一些左下角在原點的與座標軸平行的矩形, 後來的矩形會覆蓋掉原來矩形的邊,求最後所有能看見的邊的總長度。 *做法 正向做應該很難想,我們考慮最後一個新增的矩形一定是完整的,

而對於之後的矩形我們只要把兩條邊分開考慮, xxiyx與x軸平行的邊對答案能做的貢獻為xi-他所在的y的最大的x yyixy與y軸平行的邊對答案能做的貢獻為yi-他所在的x的最大的y x,y我們對x,y分別離散化建立權值線段樹 每次先查詢每條邊所能做的貢獻 0xiymax,0yixmax更新0-xi之間的y的max,更新0-yi之間的x的max LazyO(nlogn)單點查詢區間更新,用Lazy就可以做到O(nlogn) 程式碼

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<<x<<endl const int maxn = 1e5+10; int x[maxn],y[maxn]; int Hash_x[maxn],Hash_y[maxn]; int getid(int a[],int n,int x) { return lower_bound(a+1,a+1+n,x)-a; } struct T { int l,r,mid,val; int add; }tree_x[maxn<<2],tree_y[maxn<<2]; void push_up(T tree[],int rt) { tree[rt].val=max(tree[rt<<1].val,tree[rt<<1|1].val); } void push_down(T tree[],int rt) { if(tree[rt].add) { tree[rt<<1].add=max(tree[rt<<1].add,tree[rt].add); tree[rt<<1].val=max(tree[rt<<1].val,tree[rt].add); tree[rt<<1|1].add=max(tree[rt<<1|1].add,tree[rt].add); tree[rt<<1|1].val=max(tree[rt<<1|1].val,tree[rt].add); tree[rt].add=0; } } void build(T tree[],int rt,int l,int r) { tree[rt].l=l; tree[rt].r=r; tree[rt].add=0; if(l==r) return ; int mid=tree[rt].mid=l+r>>1; build(tree,rt<<1,l,mid); build(tree,rt<<1|1,mid+1,r); push_up(tree,rt); } void update(T tree[],int rt,int l,int r,int val) { if(r<tree[rt].l||l>tree[rt].r) return ; if(l<=tree[rt].l&&tree[rt].r<=r) { tree[rt].add=max(tree[rt].add,val); tree[rt].val=max(tree[rt].val,val); return ; } push_down(tree,rt); if(l<=tree[rt].mid) update(tree,rt<<1,l,r,val); if(r>tree[rt].mid) update(tree,rt<<1|1,l,r,val); push_up(tree,rt); } int query(T tree[],int rt,int pos) { if(tree[rt].l==tree[rt].r) return tree[rt].val; push_down(tree,rt); long long ans; if(pos<=tree[rt].mid) ans=query(tree,rt<<1,pos); else ans=query(tree,rt<<1|1,pos); push_up(tree,rt); return ans; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]); for(int i=1;i<=n;i++) { Hash_x[i]=x[i]; Hash_y[i]=y[i]; } sort(Hash_x+1,Hash_x+1+n); sort(Hash_y+1,Hash_y+1+n); int d_x=unique(Hash_x+1,Hash_x+1+n)-Hash_x-1; int d_y=unique(Hash_y+1,Hash_y+1+n)-Hash_y-1; build(tree_x,1,1,d_x); build(tree_y,1,1,d_y); long long ans=0; for(int i=n;i>=1;i--) { int posx=getid(Hash_x,d_x,x[i]); int posy=getid(Hash_y,d_y,y[i]); int tmp=query(tree_x,1,posx); if(tmp<y[i]) ans+=y[i]-tmp; tmp=query(tree_y,1,posy); if(tmp<x[i]) ans+=x[i]-tmp; update(tree_x,1,1,posx,y[i]); update(tree_y,1,1,posy,x[i]); } printf("%lld\n",ans); return 0; }