bzoj1935 [Shoi2007]园丁的烦恼

bzoj1935 [Shoi2007]园丁的烦恼

有N个点坐标为(xi,yi),M次询问,询问(a,b)-(c,d)的矩形内有多少点。

0≤n≤500000,1≤m≤500000,0≤xi,yi≤10000000

看完数据范围傻眼系列。

做法:

离线处理

因为这个范围肯定不能把x y都离散,

所以只把点和询问的y坐标放在一起都离散化,然后一起按x坐标排序,

再开一个树状数组,求出每个需要的点的二维前缀和。

不理解的话拿画图板画一下就好了。

细节见代码

#include<bits/stdc++.h>
#define MAXN 500005
#define lowbit(a) (a&-a)
using namespace std;
inline int read(){
    int x=0,t=1;char c;c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)t=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘,c=getchar();}
    return x*t;
}
int N,M,Y[3*MAXN],cnt,tx[MAXN],ty[MAXN],sum[MAXN][5],
xa[MAXN],ya[MAXN],xb[MAXN],yb[MAXN],c[MAXN*3],siz;
struct Work{
    int x,y,id,f;
    bool operator <(const Work z)const{
        return x<z.x||(x==z.x&&f<z.f);
    }
}a[5*MAXN];
inline void add(int pos,int val){
    for(;pos<=siz;pos+=lowbit(pos))
        c[pos]+=val;
}
inline int query(int pos){
    int s=0;
    for(;pos>0;pos-=lowbit(pos))
        s+=c[pos];
    return s;
}
int main()
{
    N=read(),M=read();
    for(int i=1;i<=N;i++){
        tx[i]=read()+1,ty[i]=read();
        Y[++cnt]=ty[i];
    }
    for(int i=1;i<=M;i++){
        xa[i]=read()+1,ya[i]=read(),xb[i]=read()+1,yb[i]=read();
        Y[++cnt]=ya[i],Y[++cnt]=yb[i];
    }
    sort(Y+1,Y+1+cnt);
    siz=unique(Y+1,Y+1+cnt)-Y-1;    cnt=0;
    for(int i=1;i<=N;i++){
        ty[i]=lower_bound(Y+1,Y+1+siz,ty[i])-Y;       //把点和询问放在一起离散化,然后排序。
        a[++cnt]=(Work){tx[i],ty[i],0,0};
    }
    for(int i=1;i<=M;i++){
        ya[i]=lower_bound(Y+1,Y+1+siz,ya[i])-Y;
        yb[i]=lower_bound(Y+1,Y+1+siz,yb[i])-Y;
        a[++cnt]=(Work){xb[i],  yb[i],  i,1};         //把需要计算矩阵和需要的四个点加进操作数组中,二位前缀和不用解释吧。
        a[++cnt]=(Work){xa[i]-1,ya[i]-1,i,2};
        a[++cnt]=(Work){xa[i]-1,yb[i],i,3};
        a[++cnt]=(Work){xb[i],ya[i]-1,i,4};
    }
    sort(a+1,a+1+cnt);
    for(int i=1;i<=cnt;i++){
        if(a[i].id)                      //遇到点把他加进树状数组
            sum[a[i].id][a[i].f]=query(a[i].y);
        else
            add(a[i].y,1);
    }
    for(int i=1;i<=M;i++)
        printf("%d\n",sum[i][1]+sum[i][2]-sum[i][3]-sum[i][4]);
    return 0;
}

附个离散写法

sort -> unique -> lower_bound

时间: 2024-10-10 10:05:07

bzoj1935 [Shoi2007]园丁的烦恼的相关文章

题解 P2163 【[SHOI2007]园丁的烦恼】

题目链接 Solution [SHOI2007]园丁的烦恼 题目大意:给定\(n\)棵树的坐标,每次询问以\((a,b)\)为左下端点,\((c,d)\)为右下端点的矩形内树的数量 题目大意:常规操作先二维前缀和一下: 记\(S_{i,j}\)为左下端点\((0,0)\),右上端点\((i,j)\)内的树的数量 然后每组询问的答案就是 \(ans = S_{c,d} - S_{a - 1,d} - S_{c,b-1}+S_{a-1,b-1}\) 我们的点就分为了两类:询问点和修改点 对于每个询问

BZOJ 1935 SHOI2007 园丁的烦恼 树状数组

题目大意:给定平面上的一些点,多次询问某个矩形中有多少个点 将每个询问拆成4个 然后把所有询问和点都按照横坐标排序 对于每个询问,将所有x值小于等于这个询问的x的点的y值加入树状数组 然后在树状数组上查询小于等于这个询问的y值的点的数量 别被1000W吓到了 如果不爆内存的话1E也是能搞的 套个log就没多少了 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm&

P2163 [SHOI2007]园丁的烦恼

#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=3e6+5; const int M=1e7+5; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()

luoguP2163 [SHOI2007]园丁的烦恼

https://www.luogu.org/problem/P2163 题意 如摘要所示,二位静态数点 分析 先,按照y为第一关键字,x为第二关键字排序,把n个数点,和询问的4*m个点都加进去,然后优先数点 这样就可以用关于 x 的树状数组进行求和和加点操作,进而用查询矩形的四个端点的sum加加减减就好了 可是这代码不知道为什么RE了一个点,,,以后再调吧 小伙伴们记得提醒博主这个傻子哦... 或者大佬能帮我调调.... (RE对于博主来说,只是常规操作..) #include<cstdio>

$[SHOI2007]$ 园丁的烦恼 二维数点/树状数组

\(Sol\) 设一个矩阵的左上角为\((x_1,y_1)\),右下角为\((x_2,y_2)\),\(s_{x,y}\)是到\((1,1)\)二维前缀和,那么这个矩阵的答案显然是\(s_{x_2,y_2}-s_{x_1-1,y_2}-s_{x_2,y_1-1}+s_{x_1-1,x_2-1}\).考虑把每个询问拆成这么四个二维前缀和的询问.将所有询问的\(s_{x,y}\)按照\(x\)排序,依次计算,这样我们就可以忽略\(x\)的限制而只考虑\(y\)的限制了.每次扫到一个询问,先把\(x\

BZOJ1935: [Shoi2007]Tree 园丁的烦恼

1935: [Shoi2007]Tree 园丁的烦恼 Description 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: "最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么--" "那么本质上它是一个深度优先搜索,陛下",园丁深深地向国王鞠了一躬. "嗯--我听说有一种怪物叫九头蛇,它非常贪吃苹果树--" &

bzoj1382 1935: [Shoi2007]Tree 园丁的烦恼

1935: [Shoi2007]Tree 园丁的烦恼 Time Limit: 15 Sec  Memory Limit: 357 MBSubmit: 1261  Solved: 578[Submit][Status][Discuss] Description 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: "最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么--&

1935: [Shoi2007]Tree 园丁的烦恼

1935: [Shoi2007]Tree 园丁的烦恼 Time Limit: 15 Sec  Memory Limit: 357 MBSubmit: 648  Solved: 273[Submit][Status][Discuss] Description 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: “最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么……”

【BZOJ1935/4822】[Shoi2007]Tree 园丁的烦恼/[Cqoi2017]老C的任务 树状数组

题意:两道题差不多,都是给你一堆平面上的点,每个点有权值,然后m次询问求某一矩形区域内的点权和 题解:先离散化,然后将询问拆成左右两条线段,然后将点和这些线段一起按x坐标排序,在y轴上维护树状数组.然后询问的答案就是两条线段上点权和之差 BZOJ1935: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int