[BZOJ4237]稻草人/[JOISC2014]かかし

[BZOJ4237]稻草人/[JOISC2014]かかし

题目大意:

平面上\(n(n\le2\times10^5)\)个点,若一个矩形各边与坐标轴平行,左下角和右上角都在\(n\)个点之中,且内部不包含其它的点,则这个矩形是合法的。问给定的点中包含多少合法的矩形?

思路:

将点按照\(x\)排序,使用CDQ分治。分治的两边分别按照\(y\)排序,左右两遍分别维护一个单调栈。左边的单调栈按照\(x\)单调递减,右边的单调栈按照\(x\)单调递增。右边的栈中的点作为右上角,用树状数组维护左边的单调栈中的点,确定有多少点可以作为左下角。

时间复杂度\(\mathcal O(n\log^2n)\)

源代码:

#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
#include<functional>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
typedef long long int64;
const int N=2e5+1;
int n;
int64 ans;
struct Node {
	int x,y;
};
Node a[N];
inline bool cmp1(const Node &p1,const Node &p2) {
	if(p1.x==p2.x) {
		return p1.y<p2.y;
	}
	return p1.x<p2.x;
}
inline bool cmp2(const Node &p1,const Node &p2) {
	return p1.y<p2.y;
}
inline bool cmp3(const int &p1,const int &p2) {
	return a[p1].y>a[p2].y;
}
int s1[N],s2[N],t1,t2;
class FenwickTree {
	private:
		int val[N];
		int lowbit(const int &x) const {
			return x&-x;
		}
	public:
		void modify(int p,const int &x) {
			for(;p<=n;p+=lowbit(p)) val[p]+=x;
		}
		int query(int p) const {
			int ret=0;
			for(;p;p-=lowbit(p)) ret+=val[p];
			return ret;
		}
};
FenwickTree t;
void cdq(const int &b,const int &e) {
	if(b==e) return;
	const int mid=(b+e)>>1;
	cdq(b,mid);
	cdq(mid+1,e);
	int p=b,q=mid+1;
	for(;q<=e;q++) {
		while(t2!=0&&a[s2[t2]].x>a[q].x) t2--;
		for(;p<=mid&&a[p].y<a[q].y;p++) {
			while(t1!=0&&a[s1[t1]].x<a[p].x) {
				t.modify(a[s1[t1--]].y,-1);
			}
			t.modify(a[s1[++t1]=p].y,1);
		}
		ans+=t.query(a[q].y)-t.query(a[s2[t2]].y);
		s2[++t2]=q;
	}
	while(t1!=0) t.modify(a[s1[t1--]].y,-1);
	t2=0;
	std::inplace_merge(&a[b],&a[mid]+1,&a[e]+1,cmp2);
}
std::vector<int> v;
int main() {
	n=getint();
	for(register int i=1;i<=n;i++) {
		a[i].x=getint();
		a[i].y=getint();
	}
	for(register int i=1;i<=n;i++) v.push_back(a[i].x);
	std::sort(v.begin(),v.end());
	for(register int i=1;i<=n;i++) {
		a[i].x=std::lower_bound(v.begin(),v.end(),a[i].x)-v.begin()+1;
	}
	v.clear();
	for(register int i=1;i<=n;i++) v.push_back(a[i].y);
	std::sort(v.begin(),v.end());
	for(register int i=1;i<=n;i++) {
		a[i].y=std::lower_bound(v.begin(),v.end(),a[i].y)-v.begin()+1;
	}
	v.clear();
	std::sort(&a[1],&a[n]+1,cmp1);
	cdq(1,n);
	printf("%lld\n",ans);
	return 0;
}
posted @ 2018-08-11 20:59  skylee03  阅读(206)  评论(0编辑  收藏  举报