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


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

    题目大意:

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

    思路:

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

    时间复杂度(mathcal O(nlog^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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    浅谈Cauchy不等式
    终于结束的起点——CSP-S 2019 第二轮游记
    LOJ 10172 涂抹果酱
    数字表格
    CSP-S 2019 第一轮 游记
    20191011模拟赛
    Luogu 2327 扫雷
    NOIAC 30 candy
    FormData文件上传
    sde表空间无法导入数据和编辑
  • 原文地址:https://www.cnblogs.com/skylee03/p/9461085.html
Copyright © 2020-2023  润新知