两个区间范围限制 可以考虑主席树 如果知道x1,x2范围y值的分布 在y中进行[y1,y2]的区间和查询不就行了吗 明显的主席树
#include
using namespace std;
typedef long long ll;
const int maxn=100010;
struct node
{
int x,y,ans;
bool friend operator<(node f1,node f2)
{
return f1.x<f2.x;
}
}a[maxn];
int X[maxn],Y[maxn];
int nodeNum;
int L[maxn<<5],R[maxn<<5],sum[maxn<<5];
int T[maxn];
int build(int l,int r) //建一个空树(所有sum[i]都为0)
{
int num=++nodeNum; //num为当前节点编号
if(l!=r)
{
int m=(l+r)>>1;
L[num]=build(l,m);
R[num]=build(m+1,r);
}
return num; //返回当前节点的编号
}
int update(int pre,int l,int r,int x,int k) //pre为旧树该位置节点的编号
{
int num=++nodeNum; //新建节点的编号
L[num]=L[pre];R[num]=R[pre];sum[num]=sum[pre]+k;
//该节点左右儿子初始化为旧树该位置节点的左右儿子
//因为插入的a[i](或Hash[x])在该节点所代表的区间中 所以sum++
if(l!=r)
{
int m=(l+r)>>1;
if(x<=m) L[num]=update(L[pre],l,m,x,k);
//x出现在左子树 因此右子树保持与旧树相同 修改左子树
else R[num]=update(R[pre],m+1,r,x,k);
}
return num;
}
int query(int u,int v,int l,int r,int lx,int rx) //第k小
{
if(lx<=l&&r<=rx)
return sum[v]-sum[u];
int m=(l+r)>>1;
int ans=0;
if(lx<=m)
ans+=query(L[u],L[v],l,m,lx,rx);
if(rx>m)
ans+=query(R[u],R[v],m+1,r,lx,rx);
return ans;
}
int main()
{
int M;
scanf("%d",&M);
while(M--)
{
ll n;int m,q;
nodeNum=0;
memset(sum,0,sizeof(sum));
memset(X,0,sizeof(X));
memset(Y,0,sizeof(Y));
memset(T,0,sizeof(T));
memset(L,0,sizeof(L));
memset(R,0,sizeof(R));
memset(a,0,sizeof(a));
scanf("%lld %d %d",&n,&m,&q);
for(int i=1;i<=m;i++)
{
ll x,y,ans;
scanf("%lld %lld",&x,&y);
a[i].x=x,a[i].y=y;
X[i]=x;Y[i]=y;
x=x-n/2-1;y=y-n/2-1;
ll t=max(abs(x),abs(y));
if(x>=y)
ans=n*n-4*t*t-2*t-x-y;
else
ans=n*n-4*t*t+2*t+x+y;
ll ten=10;
while(ans)
{
a[i].ans=a[i].ans+ans%ten;
ans/=ten;
}
}
sort(X+1,X+1+m);
sort(Y+1,Y+1+m);
sort(a+1,a+1+m);
int size=m;
T[0]=build(1,size);
for(int i=1;i<=m;i++)
{
int x=lower_bound(Y+1,Y+1+m,a[i].y)-Y;
T[i]=update(T[i-1],1,size,x,a[i].ans);
}
while(q--)
{
int x1,y1,x2,y2;
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
int l=lower_bound(X+1,X+1+m,x1)-X-1,r=upper_bound(X+1,X+1+m,x2)-X-1;
printf("%d\n",query(T[l],T[r],1,size,lower_bound(Y+1,Y+1+m,y1)-Y,upper_bound(Y+1,Y+1+m,y2)-Y-1));
}
}
}