题目
给你一个奇数的n,按照以下图的规律构造矩阵
给你m个坐标,每个坐标上都有这些数字,而其他坐标都为0
给你p次询问,每次询问给你一个矩形,求矩形内的数字的数位之和
例如 19 和 25 和 591的数位之和为 10 + 7 + 15 = 32
思路
x = x − n/2 − 1;
y = x − n/2 − 1 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; //在向左与向下的路线上
通过规律可以得出每个坐标的位置
将一个坐标上的值得出来
一个矩形的和可以拆成四个矩形
因此一次询问就可以看出求四次二维前缀和 标记每次询问是加还是减;
将宫殿和询问按 y 坐标排序 维护一个带修树状数组
每加入一个值添加其值
每加入一个询问就求其前缀和
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 5;
struct node1 {
ll x, y, val;
node1(ll _x = 0, ll _y = 0, ll _val = 0): x(_x), y(_y), val(_val) {}
bool operator < (node1 b) {
return y < b.y;
}
} point[maxn];
struct node2 {
ll x, y, id, flag;
node2(ll _x = 0, ll _y = 0, ll _id = 0, ll _flag = 0): x(_x), y(_y), id(_id), flag(_flag) {}
bool operator < (node2 b) {
return y < b.y;
}
} mar[maxn << 2];
ll n, m, p;
ll cal(ll x, ll y) {
ll qs = n / 2, q = min(n - y + 1, min(n - x + 1, min(x, y))) - 1;
if (x == qs + 1 && y == qs + 1) {
return n * n;
}
ll ans = 1ll * q * (8 * qs + 8 * (qs - q + 1)) / 2;
if (n - x == q) {
ans += n - q - y + 1;
} else if (y - 1 == q) {
ans += n - 2 * q + 1 + n - q - 1 - x;
} else if (x - 1 == q) {
ans += n - 2 * q + 1 + n - 2 * q - 2 + y - q - 1;
} else {
ans += n - 2 * q + 1 + n - 2 * q - 2 + n - 2 * q - 1 + x - q - 1;
}
ll sum = 0;
while(ans) {
sum += ans % 10;
ans /= 10;
}
return sum;
}
ll lowbit(ll x) {
return x&(-x);
}
ll bit[maxn << 1];
void add(ll x, ll val) {
if(x == 0) {
return;
}
while(x < maxn) {
bit[x] += val;
x += lowbit(x);
}
}
ll que(ll x) {
ll ans = 0;
while(x) {
ans += bit[x];
x -= lowbit(x);
}
return ans;
}
ll ans[maxn];
int main() {
int t;
scanf("%d", &t);
while(t--) {
scanf("%lld %lld %lld", &n, &m, &p);
memset(bit, 0, sizeof(bit));
memset(ans, 0, sizeof(ans));
for(int i = 0; i < m; i++) {
ll x, y;
scanf("%lld %lld", &x, &y);
point[i] = node1(x, y, cal(x, y));
}
sort(point, point+m);
ll a, b, c, d;
for(int i = 0; i < p; i++) {
scanf("%lld %lld %lld %lld", &a, &b, &c, &d);
mar[i*4] = node2(a-1, b-1, i, 1);
mar[i*4+1] = node2(a-1, d, i, -1);
mar[i*4+2] = node2(c, b-1, i, -1);
mar[i*4+3] = node2(c, d, i, 1);
}
sort(mar, mar+p*4);
int pos = 0;
for(int i = 0; i < p*4; i++) {
while(pos < m && point[pos].y <= mar[i].y) {
add(point[pos].x, point[pos].val);
pos++;
}
ans[mar[i].id] += que(mar[i].x) * mar[i].flag;
}
for(int i = 0; i < p; i++) {
printf("%lld\n", max(0LL, ans[i]));
}
}
return 0;
}