首先O(1)算出 m个点的对应的beauty值,然后就变成了一个二维数点问题,在一个n*n的矩阵上,有m个点,q个询问
每次询问一个矩阵内的值之和。由于n的范围为1e6,二维树状数组加离散化或者二维前缀和加离散化开不下,如果用map存pair
会多加一个log 复杂度为n(logn)(logn) 会T,这里要用到二维偏序预处理加一维树状数组。
在y轴上建立树状数组,对每个点的x轴和y轴进行排序。同时每次询问要求的矩阵[a,b,c,d],就等于
前缀和+[c,d],+[a-1,b-1] , -[a-1,d], -[c,b-1] 。由于我们只要求四个矩阵点(x,y)的前缀和所以对于矩阵点之前的点我们先加进去
然后在矩阵点的时候求出前缀和更新答案,所以排序的时候我们把矩阵点也加入数组中排序。并且让矩阵点在数组中的位置位于实际点之后,同时要记录一下四个矩阵点id 方便更新答案。则对于每个矩阵的ans就为四个矩阵点的前缀和乘以他的系数之和。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t,n,m,p;
ll c[500005];
struct node
{
int x,y,val,id;
}pos[500005];
bool cmp(node a, node b)
{
if(a.x!=b.x)return a.x<b.x;
if(a.y!=b.y)return a.y<b.y;
if(a.val!=b.val)return a.val>b.val;
}
int lowbit(int x){return x&(-x);}
void add(int x,int d)
{
while(x<=n)
{
c[x]+=d;
x+=lowbit(x);
}
return ;
}
ll sum(int x)
{
ll res=0;
while(x>0)
{
res+=c[x];
x-=lowbit(x);
}
return res;
}
int get_val(int x, int y, int n)
{
int w=min(min(x-1,y-1),min(n-x,n-y));
ll v=2LL*(n-1+n-1-2*(w-1))*w;
n-=w*2;
x-=w;
y-=w;
if(x==n&&y>1) v+=1LL*(n-y+1);
else if(y==1&&x>1) v+=1LL*(n-1+n-x+1);
else if(x==1&&y<n) v+=1LL*(2*(n-1)+y);
else v+=1LL*(3*(n-1)+x);
int tot=0;
while(v)
{
tot+=v%10;
v=v/10;
}
return tot;
}
ll ans[100005];
int num;
void init()
{
for(int i=0;i<=n;i++)
{
c[i]=0;
}
num=0;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&p);
init();
for(int i=1;i<=m;i++)
{
++num;
int a,b;
scanf("%d%d",&a,&b);
pos[num].x=a;pos[num].y=b;
pos[num].id=get_val(a,b,n);
pos[num].val=1000;
}
int a,b,c,d;
for(int i=1;i<=p;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
pos[++num].x=c;pos[num].y=d;pos[num].val=1;pos[num].id=i;
pos[++num].x=a-1;pos[num].y=b-1;pos[num].val=1;pos[num].id=i;
pos[++num].x=a-1;pos[num].y=d;pos[num].val=-1;pos[num].id=i;
pos[++num].x=c;pos[num].y=b-1;pos[num].val=-1;pos[num].id=i;
ans[i]=0;
}
sort(pos+1,pos+1+num,cmp);
//for(int i=1;i<=num;i++)cout<<pos[i].x<<" "<<pos[i].y<<" "<<pos[i].val<<" "<<pos[i].id<<endl;
for(int i=1;i<=num;i++)
{
if(pos[i].val==1000)
{
add(pos[i].y,pos[i].id);
}
else
{
ans[pos[i].id]+=1ll*sum(pos[i].y)*pos[i].val;
//cout<<ans[pos[i].id]<<endl;
}
}
for(int i=1;i<=p;i++)
{
printf("%lld\n",ans[i]);
}
}
return 0;
}