题目链接、
y轴压缩,维护x的树状数组
矩阵查询变成两个
/*author:revolIA*/
#include<bits/stdc++.h>
#define HEAP(...) priority_queue<__VA_ARGS__ >
#define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >
using namespace std;
typedef long long ll;
template <class T> T max(T &a,const T &b){return a>b?a:b;}
template <class T> T min(T &a,const T &b){return a<b?a:b;}
const int maxn = 1e6+7,inf = 1e9+7;
ll getval(int x,int y,int n){
ll t = min(min(x, y), min(n - x + 1, n - y + 1));
ll ta = 4 * (t - 1) * (n - t + 1);
if (x == n - t + 1) ta += n - t - y + 2;
else if (x == t) ta += 2 * n - 5 * t + y + 3;
else if (y == t) ta += 2 * n - 3 * t - x + 3;
else ta += 3 * n - 7 * t + x + 4;
ll ans = 0;
while(ta){
ans += ta%10;
ta /= 10;
}
return ans;
}
ll Tree[maxn],ans[maxn],n,m,p,T;
void add(int x,ll val){while(x<=n)Tree[x] += val,x+=x&-x;}
ll query(int x,ll ans = 0){while(x)ans += Tree[x],x-=x&-x;return ans;}
struct node{int x,y,pos,opt;};
vector<pair<int,ll>> Add[maxn];
vector<node> Query[maxn];
int main(){
scanf("%lld",&T);
while(T--){
scanf("%lld%lld%lld",&n,&m,&p);
for(int i=1;i<=n;i++)Add[i].clear(),Query[i].clear();
for(int i=1,x,y;i<=m;i++){//insert
scanf("%d%d",&x,&y);
Add[y].push_back({x,getval(x,y,1LL*n)});
}
for(int i=1,x1,y1,x2,y2;i<=p;i++){//ask
ans[i] = 0;//initial
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
Query[y2].push_back({x1,x2,i,1});
Query[y1-1].push_back({x1,x2,i,-1});
}
for(int i=1;i<=n;i++)Tree[i] = 0;
for(int i=1;i<=n;i++){
for(auto j:Add[i])add(j.first,j.second);
for(auto j:Query[i])ans[j.pos] += j.opt*(query(j.y)-query(j.x-1));
}
for(int i=1;i<=p;i++)printf("%lld\n",ans[i]);
}
return 0;
}