1. 程式人生 > >[BZOJ]4237: 稻草人

[BZOJ]4237: 稻草人

沒有 type queue scrip 容易 efi getch tps cst

題解: 這題很容易繞繞繞

我們考慮分治一下 按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

[BZOJ]4237: 稻草人