P1856 [USACO5.5]矩形周长Picture
$len$ $sum$ $num$ $flag\_l$ $flage\_r$分别表示该区间
覆盖长度--整体覆盖次数--覆盖段数--左右端点是否覆盖
将上下边按高度排序不断扫下来
$num$是用来处理高度的
inline void Update(LL now,LL l,LL r){ if(tree[now].sum){ tree[now].num=1, tree[now].len=r-l+1, tree[now].flag_l=tree[now].flag_r=1; }else if(l==r){ tree[now].len=tree[now].num=tree[now].flag_l=tree[now].flag_r=0; }else{ LL son0=now<<1,son1=son0|1; tree[now].len=tree[son0].len+tree[son1].len, tree[now].num=tree[son0].num+tree[son1].num; if(tree[son0].flag_r&&tree[son1].flag_l) --tree[now].num; tree[now].flag_l=tree[son0].flag_l, tree[now].flag_r=tree[son1].flag_r; } }
现在来理解一下更新
如果该区间至少覆盖了一次,显然只覆盖段数为$1$,注意线段树里长度是以段分的
如果没被覆盖
$(1)$叶子节点,全部清空
$(2)$长度$=$左右子树长度 覆盖段数也差不多,再加一下合并
My complete code:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<string> using namespace std; typedef long long LL; const LL maxn=1e5; inline LL Read(){ LL x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }return x*f; } struct node{ LL l,r,h,val; }a[maxn]; struct code{ LL len,sum,num,flag_l,flag_r; }tree[maxn]; LL n,mi,mx,ans,num,last; inline bool cmp(node x,node y){ return x.h<y.h||(x.h==y.h&&x.val>y.val); } inline void Update(LL now,LL l,LL r){ if(tree[now].sum){ tree[now].num=1, tree[now].len=r-l+1, tree[now].flag_l=tree[now].flag_r=1; }else if(l==r){ tree[now].len=tree[now].num=tree[now].flag_l=tree[now].flag_r=0; }else{ LL son0=now<<1,son1=son0|1; tree[now].len=tree[son0].len+tree[son1].len, tree[now].num=tree[son0].num+tree[son1].num; if(tree[son0].flag_r&&tree[son1].flag_l) --tree[now].num; tree[now].flag_l=tree[son0].flag_l, tree[now].flag_r=tree[son1].flag_r; } } LL ci; void Add(LL now,LL l,LL r,LL lt,LL rt,LL v){ if(lt<=l&&rt>=r){ tree[now].sum+=v, Update(now,l,r); return; } LL mid=(l+r)>>1,son0=now<<1,son1=son0|1; if(lt<=mid) Add(son0,l,mid,lt,rt,v); if(rt>mid) Add(son1,mid+1,r,lt,rt,v); Update(now,l,r); } int main(){ n=Read(); for(LL i=1;i<=n;++i){ LL x1=Read(),y1=Read(),x2=Read(),y2=Read(); mx=max(mx,max(x1,x2)), mi=min(mi,min(x1,x2)), a[++num]=(node){x1,x2,y1,1}, a[++num]=(node){x1,x2,y2,-1}; } if(mi<=0){ for(LL i=1;i<=num;++i) a[i].l+=-mi+1, a[i].r+=-mi+1; mx+=-mi; } sort(a+1,a+1+num,cmp); for(LL i=1;i<=num;++i){ Add(1,1,mx,a[i].l,a[i].r-1,a[i].val); while(a[i].h==a[i+1].h&&a[i].val==a[i+1].val){ ++i, Add(1,1,mx,a[i].l,a[i].r-1,a[i].val); } ans+=abs(last-tree[1].len), last=tree[1].len, ans+=2*tree[1].num*(a[i+1].h-a[i].h); } printf("%lld",ans); return 0; }