zoukankan      html  css  js  c++  java
  • 二维数点问题

    二维数点问题

    二维数点在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;	
    }
    
  • 相关阅读:
    Android OpenGL ES 2.0 (四) 灯光perfragment lighting
    Android OpenGL ES 2.0 (五) 添加材质
    冒泡排序函数
    javascript object 转换为 json格式 toJSONString
    Liunx CentOS 下载地址
    jquery 图片切换特效 鼠标点击左右按钮焦点图切换滚动
    javascript 解析csv 的function
    mysql Innodb Shutdown completed; log sequence number解决办法
    Centos 添加 yum
    javascript 键值转换
  • 原文地址:https://www.cnblogs.com/wyxdrqc/p/10655228.html
Copyright © 2011-2022 走看看