• 二维数点问题


    二维数点问题

    二维数点在OI中有着广泛的应用,很多题目正解或其部分分都可以转化为二维数点的模型.

    一般性的静态二维数点问题:

    给出平面上的(n)个点的坐标(P_i(x_i,y_i)),(Q)次查询,每次查询((a,b,c,d)),表示,求在矩形((a,b),(c,d))中的点数

    (a,b,c,d,n <= 10^5)

    数据范围都是(10^5)级别的,我们就不能运用前缀和去解决问题了

    但是可以运用二维前缀和的思想

    我们设(S(x,y))表示((0,0)(x,y))这个矩阵中点的个数

    每次询问的答案很明显是

    (S(c,d) - S(a - 1,d) - S(c,b - 1) + S(c - 1,d - 1))

    我们就将个询问拆成这四部分分解维护

    之后用扫描线的思想维护树状数组,大体思路是这样的:

    先将所有的点,和我们拆分完成之后的询问全部按照(x)进行排序

    (对于(x)这一维)之后每次扫到一个询问的(x),就把当前还剩下的小于等于(x)的点全部加上

    加上什么呢,这个点在(y)这一维的贡献(可能有点绕)

    就是我们把树状数组的下标看做权值

    当前影响的是(1- y)这个范围的点.所以在树状数组上将这个区间的贡献(+1)

    例题BZOJ1935/Luogu2163[SHOI2007]园丁的烦恼

    就是上面的问题,但是注意一下坐标有((0,0)),而树状数组(0)没有意义,所以将所有坐标整体(+1)

    另外这道题坐标范围是(10^7)级别的,按理来说应当对(y)这一维离散化,但是树状数组跑的飞快,就不管了,反正空间不会炸.

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N = 5e5 + 5;
    int c[10000003];
    int n,m;
    int ans[N];
    struct tree{
    	int x,y;	
    }v[N];
    struct ques{
    	int x,y;
    	int id,opt;	
    	ques(int xx = 0,int yy = 0,int num = 0,int o = 0){
    		x = xx,y = yy,id = num,opt = o;
    	}
    }q[N << 2];
    inline char nc(){
        #define SIZE 1000000+5
        static char buf[SIZE],*p1 = buf+SIZE,*p2 = buf+SIZE;
        if(p1 == p2){
            p1 = buf;p2 = buf+fread(buf,1,SIZE,stdin);
            if(p1 == p2) return -1;
        }
        return *p1++;
    }
    inline int read(){
        int x = 0;char ch = nc();int flag = 0;
        while(!isdigit(ch)){
            if(ch == '-') flag = -1;
            ch = nc();
        }
        while(isdigit(ch)){
            x = (x<<1) + (x<<3) + (ch^'0');
            ch = nc();
        }
        if(flag) x = -x;
        return x;
    }
    inline bool cmp1(tree x,tree y){
    	return x.x < y.x;	
    }
    inline bool cmp2(ques x,ques y){
    	return x.x < y.x;
    } 
    inline void updata(int x,int val){
    	for(;x <= n;x += x & -x) c[x] += val;	
    }
    inline int query(int x){
    	int res = 0;
    	for(;x;x -= x & -x) res += c[x];
    	return res;	
    }
    int main(){
    	int cnt = 0;
    	n = read(),m = read();
    	for(int i = 1;i <= n;++i)
    	v[i].x = read() + 1,v[i].y = read() + 1;
    	for(int i = 1;i <= m;++i){
    		int x1 = read() + 1,y1 = read() + 1,x2 = read() + 1,y2 = read() + 1;
    		q[++cnt] = ques(x2,y2,i,1);
    		q[++cnt] = ques(x1 - 1,y2,i,-1);
    		q[++cnt] = ques(x2,y1 - 1,i,-1);
    		q[++cnt] = ques(x1 - 1,y1 - 1,i,1);
    	}
    	sort(v + 1,v + n + 1,cmp1);
    	sort(q + 1,q + cnt + 1,cmp2);
    	int now = 1;
    	for(int i = 1;i <= cnt;++i){
    		while(v[now].x <= q[i].x && now <= n) 
    			updata(v[now].y,1),now++;
    		ans[q[i].id] += q[i].opt * query(q[i].y);
    	//	printf("%d %d
    ",query(q[i].y),q[i].id);
    	}
    	for(int i = 1;i <= m;++i) printf("%d
    ",ans[i]);
    	return 0;	
    }
    
  • 相关阅读:
    对NumPy中dot()函数的理解
    使用Boostrap框架写一个登录注册界面
    两种方法实现asp.net方案的前后端数据交互(aspx文件、html+ashx+ajax)
    将包含经纬度点位信息的Excel表格数据导入到ArcMap中并输出成shapefile
    [ArcGIS API for JavaScript 4.8] Sample Code-Popups-1-popupTemplate的概念和popup中属性字段值的多种表现形式
    [python爬虫]Requests-BeautifulSoup-Re库方案--robots协议与Requests库实战
    [python爬虫]Requests-BeautifulSoup-Re库方案--Requests库介绍
    [ArcGIS API for JavaScript 4.8] Sample Code-Get Started-widgets简介
    [ArcGIS API for JavaScript 4.8] Sample Code-Get Started-popups简介
    [ArcGIS API for JavaScript 4.8] Sample Code-Get Started-layers简介
  • 原文地址:https://www.cnblogs.com/wyxdrqc/p/10655228.html
Copyright © 2020-2023  润新知