bzoj 4237 稻草人

题目大意:

网格上有些点

找出一些点对使这两个点围成的矩形内没有点

思路:

我们先用cdq降低复杂度

然后对于分治的两边

左右两端分别按照y排序

然后我们对于右边的点 只需要统计出以它为右上角顶点的矩形即可

我们直接通过对于左右两边分别维护两个单调栈

左边x单减 右边x单增

然后每次在右边插入点的时候把左边y小于它的加入栈

直接在左边的栈里二分查找答案

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2139062143
10 #define ll long long
11 #define MAXN 200100
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 struct data {int x,y;}g[MAXN],s1[MAXN],s2[MAXN];
21 int n,t1,t2,pos;
22 bool cmp(data a,data b) {return (a.x==b.x&&a.y<b.y)||a.x<b.x;}
23 bool Cmp(data a,data b) {return (a.y==b.y&&a.x<b.x)||a.y<b.y;}
24 ll ans=0;
25 void cdq(int l,int r)
26 {
27     if(l==r) return;
28     int mid=l+r>>1;
29     cdq(l,mid);cdq(mid+1,r);
30     sort(g+l,g+mid+1,Cmp);sort(g+mid+1,g+r+1,Cmp);
31     t1=t2=0,pos=l;
32     for(int i=mid+1;i<=r;i++)
33     {
34         while(t1&&s1[t1].x>=g[i].x) t1--;
35         s1[++t1]=g[i];
36         while(pos<=mid&&g[pos].y<g[i].y)
37         {
38             while(t2&&s2[t2].x<=g[pos].x) t2--;
39             s2[++t2]=g[pos++];
40         }
41         ans+=(ll)(t2-(lower_bound(s2+1,s2+t2+1,s1[t1-1],Cmp)-s2)+1);
42     }
43 }
44 int main()
45 {
46     n=read(),s1[0]=s2[0]=(data){-1,-1};
47     for(int i=1;i<=n;i++) g[i].x=read(),g[i].y=read();
48     sort(g+1,g+n+1,cmp);
49     cdq(1,n);
50     printf("%lld\n",ans);
51 }
View Code

 

posted @ 2018-02-10 13:51  jack_yyc  阅读(141)  评论(0编辑  收藏  举报