[BZOJ]4237: 稻草人

题解:  这题很容易绕绕绕

我们考虑分治一下  按x坐标排序  然后对于每一段的两部分都按y排序  左右两边都维护一个单调栈(这个地方栈的顺序要想清楚  不然就会和我一样自闭一小时)  然后考虑右边对左边的贡献就行了

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}

typedef struct node{
    int x,y;
    friend bool operator<(node aa,node bb){return aa.x<bb.x;}
}node;
node d[MAXN];
ll ans;
bool cmp(node aa,node bb){return aa.x<bb.x;}
bool cmp1(node aa,node bb){return aa.y>bb.y;}
int st1[MAXN],st2[MAXN],tot1,tot2;
void cdq(int l,int r){
    if(l>=r)return ;
    int mid=(l+r)>>1;
    sort(d+l,d+mid+1,cmp1);
    sort(d+mid+1,d+r+1,cmp1);
    int tot=mid+1;tot1=tot2=0;
    for(int i=l;i<=mid;i++){
	while(tot1&&d[st1[tot1]].x<d[i].x)tot1--;
	st1[++tot1]=i;
	while(tot<=r&&d[tot].y>=d[i].y){
	    while(tot2&&d[st2[tot2]].x>d[tot].x)tot2--;
	    st2[++tot2]=tot;
	    tot++;
	}
	if(tot1==1){ans+=tot2;continue;}
	int t=d[st1[tot1-1]].y;
	int lx=1;int rx=tot2;int ans1=0;
	while(lx<=rx){
	    int midx=(lx+rx)>>1;
	    if(d[st2[midx]].y<=t)ans1=midx,rx=midx-1;
	    else lx=midx+1;
	}
	if(ans1&&ans1<=tot2)ans+=(tot2-ans1+1);
    }
    sort(d+l,d+r+1,cmp);
    cdq(l,mid);
    cdq(mid+1,r);
}

int main(){
    int n=read();
    inc(i,1,n)d[i].x=read(),d[i].y=read();
    sort(d+1,d+n+1);
    ans=0;
    cdq(1,n);
    printf("%lld\n",ans);
}

  

4237: 稻草人

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 1781  Solved: 788
[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

 

posted @ 2019-02-08 01:38  wang9897  阅读(217)  评论(0编辑  收藏  举报