bzoj 4237 稻草人 CDQ

稻草人

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 1433  Solved: 626
[Submit][Status][Discuss]

Description

JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典。
有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地。和启示中的一样,田地需要满足以下条件:
田地的形状是边平行于坐标轴的长方形;
左下角和右上角各有一个稻草人;
田地的内部(不包括边界)没有稻草人。
给出每个稻草人的坐标,请你求出有多少遵从启示的田地的个数

 

Input

第一行一个正整数N,代表稻草人的个数
接下来N行,第i行(1<=i<=N)包含2个由空格分隔的整数Xi和Yi,表示第i个稻草人的坐标

 

Output

输出一行一个正整数,代表遵从启示的田地的个数

 

Sample Input

4
0 0
2 2
3 4
4 3

Sample Output

3

HINT

 

所有满足要求的田地由下图所示:

 

1<=N<=2*10^5

0<=Xi<=10^9(1<=i<=N)

0<=Yi<=10^9(1<=i<=N)

Xi(1<=i<=N)互不相同。

Yi(1<=i<=N)互不相同。

 题解:这题就是就是统计问题,经典的CDQ,因为每个x,y都不同,好办得不行
   按行分治,然后两边列排序,即可,维护一下,其实可以优化到n log n,外面可以预处理掉。
   但是n log ^2n可以过
 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 typedef long long LL;
 9 const int MAXN = 200011;
10 int n,stack[MAXN],top,stack2[MAXN],tail;
11 LL ans;
12 struct node{ int x,y; }a[MAXN];
13 inline bool cmpx(node q,node qq){ return q.x<qq.x; }
14 inline bool cmpy(node q,node qq){ return q.y<qq.y; }
15 inline int getint(){
16     int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
17     if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
18 }
19  
20 inline void solve(int l,int r){
21     if(l==r) return ; sort(a+l,a+r+1,cmpy); int mid=(l+r)>>1;
22     sort(a+l,a+mid+1,cmpx);//down
23     sort(a+mid+1,a+r+1,cmpx);//up
24     top=tail=0; int now=l,L,R,pos,mm,cp;
25     for(int i=mid+1;i<=r;i++) {
26         while(top>0 && a[stack[top]].y>=a[i].y) top--;
27         stack[++top]=i;
28  
29         while(now<=mid && a[now].x<a[i].x) {
30             while(tail>0 && a[stack2[tail]].y<=a[now].y) tail--;
31             stack2[++tail]=now;
32             now++;
33         }
34  
35         L=1; R=tail; pos=-1; cp=a[stack[top-1]].x;
36         while(L<=R) {
37             mm=(L+R)>>1;
38             if(a[stack2[mm]].x>cp) pos=mm,R=mm-1;
39             else L=mm+1;
40         }
41         if(pos!=-1) ans+=tail-pos+1;
42     }
43     solve(l,mid); solve(mid+1,r);
44 }
45  
46 inline void work(){
47     n=getint(); for(int i=1;i<=n;i++) a[i].x=getint(),a[i].y=getint();
48     a[0].x=a[0].y=-1;
49     solve(1,n);
50     printf("%lld",ans);
51 }
52  
53 int main()
54 {
55     work();
56     return 0;
57 }

 

posted @ 2018-03-31 15:15  Kaiser-  阅读(179)  评论(0编辑  收藏  举报