BZOJ 4237: 稻草人
4237: 稻草人
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 661 Solved: 286
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
0 0
2 2
3 4
4 3
Sample Output
HINT
Source
JOI 2013~2014 春季training合宿 竞技3 By PoPoQQQ
思(心)考(塞)历程:
晚上看ysq大佬(%%%)秒切NeighThorn做过的题的时候听到玉环在思考这题...然后NeighThorn和YouSiki果断弃掉NT做过的水题来思考YYH大佬的神题...
然后两个人对着屏幕和草稿纸陷入了深思...
一千八百万年之后NT赶脚自己YY出了一个漏洞百出的方法...(真的是漏洞百出...
感觉我们可以统计每个点对答案的贡献,因为这是个二维的东西,所以可能可以通过分治什么的降到一维...
我们把所有的点按照x轴坐标排序,然后对y坐标分治,这样我们统计对于上层的每个节点下层有多少个节点可以和其构成合法答案...
如果下层的点出现了这种情况...显然对于3节点来说1节点是没有用的...
所以我们对于下层节点维护一个y坐标单调递减的栈,对于上层的每个节点在下层的单调栈里二分答案...
然后被YouSiki大佬D得很惨...虽然他也被NT卡掉了(hia~hia~hia~...
然后NT满心欢喜地对YouSiki说:“你去写吧,我懒得写了..."被YouSiki严肃地拒绝了...
对于一切早已习惯并且淡然了的NT回到电脑屏幕前开始发呆,忽然发现这样是错误的,然后错的还很明显...(所以NT和YouSiki的脑子都锈掉了???
于是NT和YouSiki再次经过了和平的争吵之后YouSiki童鞋说出了正解...
我们现在不对上层的每个节点去寻找答案,而是直接计算跨越上下层的合法矩形个数...
我们对于上层节点维护y坐标单调递增的栈,下层节点维护y坐标单调递减的栈...
就是酱紫:
我们枚举上面的点,对于上面的某个点a我们要找到它前面的第一个高度小于它的点来卡住它的下面的点b,就是说下面二分的时候的x坐标是要通过b的x坐标来卡边界的...
一个分治里面有个二分...时间复杂度$O(nlog^{2}n)$...
然后NT表示YouSiki太厉害了...然后大爷就又愉快地开始了每天必做功课:催人...
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> //by NeighThorn using namespace std; const int maxn=200000+5; int n,cnt1,cnt2,top1,top2,mp[2][maxn]; long long ans; struct M{ int x,y; friend bool operator < (M a,M b){ return a.x<b.x; } }stk[2][maxn],pos[maxn],q[maxn]; inline void CDQ(int l,int r){ if(l==r) return; int mid=(l+r)>>1,b1=l,b2=mid+1; for(int i=l;i<=r;i++){ if(pos[i].y<=mid) q[b1++]=pos[i]; else q[b2++]=pos[i]; } memcpy(pos+l,q+l,sizeof(M)*(r-l+1)); top1=top2=0; for(int i=l,j=mid+1;j<=r;j++){ while(i<=mid&&pos[i].x<pos[j].x){ while(top1&&stk[0][top1].y<pos[i].y) top1--; stk[0][++top1]=pos[i];i++; } while(top2&&stk[1][top2].y>pos[j].y) top2--; stk[1][++top2]=pos[j]; ans+=top1-(lower_bound(stk[0]+1,stk[0]+top1+1,stk[1][top2-1])-stk[0])+1; } CDQ(l,mid),CDQ(mid+1,r); } signed main(void){ scanf("%d",&n);ans=0; for(int i=1;i<=n;i++) scanf("%d%d",&pos[i].x,&pos[i].y),mp[0][i]=pos[i].x,mp[1][i]=pos[i].y; sort(mp[0]+1,mp[0]+n+1);sort(mp[1]+1,mp[1]+n+1); cnt1=unique(mp[0]+1,mp[0]+n+1)-mp[0]-1,cnt2=unique(mp[1]+1,mp[1]+n+1)-mp[1]-1; for(int i=1;i<=n;i++) pos[i].x=lower_bound(mp[0]+1,mp[0]+cnt1+1,pos[i].x)-mp[0], pos[i].y=lower_bound(mp[1]+1,mp[1]+cnt2+1,pos[i].y)-mp[1]; sort(pos+1,pos+n+1);CDQ(1,n); printf("%lld\n",ans); return 0; }
By NeighThorn