BJ模拟 Rectangle Query【分块+bitset】

题目描述:

平面上有 n 个点,你需要回答 q 个询问:
给定 x 1 , x 2 , y 1 , y 2 ,在满足 x 1 x x 2 y 1 y y 2 的所有点 ( x , y ) 中,有多少个不同的横坐标(x坐标)和不同的纵坐标(y坐标)?
强制在线, n , q 50000

解题思路:

分块+bitset。
把坐标离散化。按x坐标从小到大排序,将这些点分为 n 块,用bitset存每一块的点,注意要按点数分块,不能按坐标分。

如果任意两个点横坐标不同且任意两个点的纵坐标不同,那么我们就可以查询横坐标在 [ x 1 , x 2 ] 的点的集合。再把y坐标按照上述过程做一次,可以得到纵坐标在 [ y 1 , y 2 ] 的点的集合。两者取交集即为所求点集。

为了去重,我们用一些小技巧,对于每一个点,我们把该点的纵坐标值改为与它横坐标相同的、纵坐标比它小的、离它最近的点。那么,我们再求一次纵坐标在 [ 1 , y 1 ) 的点的集合,与刚刚求出的答案集合取交集即为每个横坐标下纵坐标最小的点,这样就求出了不同的横坐标的个数。纵坐标同理。

时间复杂度为 O ( n n + n q 64 )

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define X first
#define Y second
using namespace std;
int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}
const int N=50005,B=250,INF=0x3f3f3f3f;
int online,n,m,S,tot,x[N],y[N];
pii p[N];vector<pii >vec[N];
struct BIT
{
    pii p[N];
    bitset<N>bit[B];
    void Init()
    {
        sort(p+1,p+n+1);
        for(int i=1;i<=n;i++)
            for(int j=(i+S-1)/S;j<=tot;j++)
                bit[j][p[i].Y]=1;
    }
    bitset<N>Get(int x)
    {
        bitset<N>ret;
        int loc=lower_bound(p+1,p+n+1,mp(x,INF))-p-1;
        if(!loc)return ret;
        int b=(loc+S-1)/S;ret=bit[b-1];
        for(int i=(b-1)*S+1;i<=loc;i++)ret[p[i].Y]=1;
        return ret;
    }
    bitset<N>Query(int l,int r){return Get(r)^Get(l-1);}
}g[4];
void decode(int &x1,int &y1,int &x2,int &y2,int ansx,int ansy)
{
    x1+=online*(ansx+ansy); y1+=online*(ansx+ansy); x2+=online*(ansx+ansy); y2+=online*(ansx+ansy);
    x1=lower_bound(x+1,x+n+1,x1)-x;
    y1=lower_bound(y+1,y+n+1,y1)-y;
    x2=upper_bound(x+1,x+n+1,x2)-x-1;
    y2=upper_bound(y+1,y+n+1,y2)-y-1;
}
int main()
{
    //freopen("lx.in","r",stdin);
    online=getint(),n=getint();
    for(int i=1;i<=n;i++)p[i].X=getint(),p[i].Y=getint();
    for(int i=1;i<=n;i++)x[i]=p[i].X,y[i]=p[i].Y;
    sort(x+1,x+n+1),sort(y+1,y+n+1);
    for(int i=1;i<=n;i++)
    {
        p[i].X=lower_bound(x+1,x+n+1,p[i].X)-x;
        p[i].Y=lower_bound(y+1,y+n+1,p[i].Y)-y;
    }
    S=sqrt(n),tot=(n+S-1)/S;
    for(int i=1;i<=n;i++)g[0].p[i]=mp(p[i].X,i),g[1].p[i]=mp(p[i].Y,i);
    g[0].Init(),g[1].Init();
    int cnt=0;
    for(int i=1;i<=n;i++)vec[p[i].X].push_back(mp(p[i].Y,i));
    for(int i=1;i<=n;i++)if(vec[i].size())
    {
        sort(vec[i].begin(),vec[i].end());
        for(int j=0;j<vec[i].size();j++)
            g[2].p[++cnt]=mp(j?vec[i][j-1].X:0,vec[i][j].Y);
        vec[i].clear();
    }
    g[2].Init();
    cnt=0;
    for(int i=1;i<=n;i++)vec[p[i].Y].push_back(mp(p[i].X,i));
    for(int i=1;i<=n;i++)if(vec[i].size())
    {
        sort(vec[i].begin(),vec[i].end());
        for(int j=0;j<vec[i].size();j++)
            g[3].p[++cnt]=make_pair(j?vec[i][j-1].X:0,vec[i][j].Y);
        vec[i].clear();
    }
    g[3].Init();
    int ansx=0,ansy=0;m=getint();
    while(m--)
    {
        int x1=getint(),y1=getint(),x2=getint(),y2=getint();
        decode(x1,y1,x2,y2,ansx,ansy);
        bitset<N>t=g[0].Query(x1,x2)&g[1].Query(y1,y2);
        ansx=(t&g[2].Get(y1-1)).count();
        ansy=(t&g[3].Get(x1-1)).count();
        printf("%d %d\n",ansx,ansy);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/cdsszjj/article/details/80184628
bj