Description
小Q最近沉迷于一款新型《打砖块》游戏。在每局游戏中,呈现在屏幕上的是一堵无限大小的墙壁。墙壁上镶嵌着
无数长度为2、宽度为1的砖块。墙壁被分成若干行,每行宽度都为1,相邻两个格子形成一个砖块。相邻两行的砖
块是间隔摆放的。墙壁从下往上行编号递增,从左往右列编号递增。如下图所示:
在游戏的一开始,有n块砖块消失了。如果两块在同一行且相邻的砖块都消失了,那么玩家可以移除它们上方与它
们都相邻的那一个砖块。请写一个程序帮助小Q计算最多可以让多少个位置没有砖块。
Input
第一行包含两个正整数n(1<=n<=100000),表示一开始消失的砖块个数。
接下来n行,每行两个整数x_i,y_i(|x_i|,|y_i|<=10^9)
分别表示每个消失的砖块的位置,即左半部分位于第x_i行第y_i列。
Output
输出一行一个整数,即没有砖块的位置个数的最大值。
从下到上扫描线,用链表维护当前哪些位置可以有砖块,每向上移一行,每个有砖块的连续段最右边的砖块消失,因此可以暴力模拟,维护一个表记录哪些点当前在连续段最右侧,在扫描线移动时删除这些点。由于一开始需要排序,时间复杂度为O(nlogn)。
#include<bits/stdc++.h> const int N=1e5+7,P=1844677; char ib[N*50],*ip=ib; int _(){ int x=0,f=1; while(*ip<48)*ip++=='-'?f=-1:0; while(*ip>47)x=x*10+*ip++-48; return x*f; } struct pos{ int x,y; bool operator<(const pos&w)const{return x<w.x;} }ps[N]; int n; struct itv{ mutable int l,r; bool operator<(const itv&w)const{return l<w.l;} }; int now=-2e9,cnt=0; struct node{ int x; bool ed,in; node*pv,*nx; }h[P]; node*at(int x,bool nw){ int w=unsigned(x)%P; while(h[w].ed){ if(h[w].x==x)return h+w; w=(w+1237)%P; } if(nw)return h[w].x=x,h[w].ed=1,h+w; return 0; } long long ans=0; node*ts[N]; int tp=0; void upd(){ ans+=cnt; ++now; for(int i=0;i<tp;++i){ if(ts[i]->nx||!ts[i]->in)ts[i--]=ts[--tp]; else{ --cnt; ts[i]->in=0; ts[i]=ts[i]->pv; if(!ts[i])ts[i--]=ts[--tp]; } } for(int i=0;i<tp;++i)ts[i]->nx=0; } void ins(int x,int y){ while(now<x&&cnt)upd(); now=x; node*p=at(y,1); if(p->in)return; p->in=1; p->pv=p->nx=0; ++cnt; node*pv=at(y-1,0),*nx=at(y+1,0); if(pv&&pv->in)(p->pv=pv)->nx=p; if(nx&&nx->in)(p->nx=nx)->pv=p; if(!p->nx)ts[tp++]=p; } int main(){ fread(ib,1,sizeof(ib),stdin); n=_(); for(int i=0;i<n;++i){ int x=_(),y=_(); ps[i]=(pos){x,(y-x)/2}; } std::sort(ps,ps+n); for(int i=0;i<n;++i)ins(ps[i].x,ps[i].y); while(cnt)upd(); printf("%lld\n",ans); return 0; }