https://nanti.jisuanke.com/t/41298
Here is a square matrix of n∗nn * nn∗n, each lattice has its value (nnn must be odd), and the center value is n∗nn * nn∗n. Its spiral decline along the center of the square matrix (the way of spiral decline is shown in the following figure:)
The grid in the lower left corner is (1,1) and the grid in the upper right corner is (n , n)
Now I can choose mmm squares to build palaces, The beauty of each palace is equal to the digital sum of the value of the land which it is located. Such as (the land value is 123213123213123213,the beautiful values of the palace located on it is 1+2+3+2+1+3=121+2+3+2+1+3=121+2+3+2+1+3=12) (666666666 -> 181818) (456456456 ->151515)
Next, we ask ppp times to the sum of the beautiful values of the palace in the matrix where the lower left grid(x1,y1x_1,y_1x1,y1), the upper right square (x2,y2x_2,y_2x2,y2).
Input
The first line has only one number TTT .Representing TTT-group of test data (T≤5)(T\le 5)(T≤5)
The next line is three number: n m pn \ m \ pn m p
The mmm lines follow, each line contains two integers the square of the palace (x,y)(x, y )(x,y)
The ppp lines follow, each line contains four integers : the lower left grid (x1,y1)(x_1,y_1)(x1,y1) the upper right square (x2,y2)(x_2,y_2)(x2,y2)
Output
Next, p1+p2...+pTp_1+p_2...+p_Tp1+p2...+pT lines: Represent the answer in turn(n≤106)(m,p≤105)(n \le 10^6)(m , p \le 10^5)(n≤106)(m,p≤105)
Solution
本题一个思维点 通过 X,Y 的坐标求出相应数字,可以通过分类讨论,或者推公式找出结论 地图大小为 一定为奇数
对于这个题而言
就转化为求任意子矩阵之和
离散化 宫殿和询问的y坐标 对于每个询问要拆成4次询问 代表 , 这点为左下节点 , 为右上节点所求得矩阵和 对于查询
; 因此一次询问就可以看出求求四次二维前缀和 标记每次询问是加还是减; 将宫殿和询问按 坐标排序
维护一个带修树状数组
ans = map[x2][y2]− map[x2][y1−1]− map[x1−1][y2]+ map[x1−1][y1−1]
每加入一个宫殿添加其值
每加入个询问就求其前缀和
相当于第一维靠排序后离线处理,第二维靠树状数组
AC Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, m, q;
int const maxn = 1000005;
class TreeArray {
public:
long long treeArray[maxn]{};
inline int lowBit(int x) {
return x & (-x);
}
void add(int treeIndex, int value) {
while (treeIndex <= maxn) {
treeArray[treeIndex] += value;
treeIndex += lowBit(treeIndex);
}
}
long long sum(int x) {
long long ans = 0;
while (x != 0) {
ans += treeArray[x];
x -= lowBit(x);
}
return ans;
}
long long query(int l, int r) {
if (l > r) {
return 0;
}
return sum(r) - sum(l - 1);
}
void clear() {
memset(treeArray, 0, sizeof(treeArray));
}
};
ll calculate(int x, int y) {
ll xx = x - n / 2 - 1; //确定该点在第几圈螺旋
ll yy = y - n / 2 - 1;
ll t = max(abs(xx), abs(yy));
if (xx >= yy)
return (ll) n * n - 4 * t * t - 2 * t - xx - yy; //在向右与向上的路线上
else return (ll) n * n - 4 * t * t + 2 * t + xx + yy; //在向左与向下的路线上
}
int resolve(ll value) {
int res = 0;
while (value) {
res += value % 10;
value /= 10;
}
return res;
}
class Point {
public:
int x, y, type, id;
explicit Point(int x = 0, int y = 0, int type = 0) : x(x), y(y), type(type), id(0) {}
bool operator<(const Point &rhs) const {
if (x == rhs.x) {
if (y == rhs.y)
return type < rhs.type;
return y < rhs.y;
} else return x < rhs.x;
}
};
class Query {
public:
int x1, y1, x2, y2;
explicit Query(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0) : x1(x1), y1(y1), x2(x2), y2(y2) {}
};
vector<Point> points;
vector<Query> queries;
vector<int> ys;
TreeArray treeArray;
map<int, map<int, ll> > matrix;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
for (cin >> t; t--;) {
matrix.clear();
points.clear();
queries.clear();
ys.clear();
treeArray.clear();
cin >> n >> m >> q;
for (int i = 0; i < m; ++i) {
int x, y;
cin >> x >> y;
points.emplace_back(x, y, 0);
ys.push_back(y);
}
for (int i = 0; i < q; ++i) {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
ys.push_back(y1 - 1);
ys.push_back(y2);
queries.emplace_back(x1, y1, x2, y2);
points.emplace_back(x2, y2, 1);
points.emplace_back(x1 - 1, y1 - 1, 1);
points.emplace_back(x1 - 1, y2, 1);
points.emplace_back(x2, y1 - 1, 1);
}
sort(points.begin(), points.end());
sort(ys.begin(), ys.end());
ys.erase(unique(ys.begin(), ys.end()), ys.end());
for (auto &point : points)
point.id = lower_bound(ys.begin(), ys.end(), point.y) - ys.begin() + 1;
for (auto &point: points) {
// cout << "point.id: " << point.id << " " << point.type << endl;
if (point.type == 0)
treeArray.add(point.id, resolve(calculate(point.x, point.y)))/*,
cout << "add " << point.id << " : " << resolve(calculate(point.x, point.y)) << endl*/;
else
matrix[point.x][point.y] = treeArray.sum(point.id)/*, cout << "sum( " << point.id << ") : matrix ["
<< point.x << ", " << point.y << "] "
<< matrix[point.x][point.y] << endl*/;
}
for (auto &query:queries) {
int x1 = query.x1, y1 = query.y1, x2 = query.x2, y2 = query.y2;
// cout << matrix[x2][y2] << " " << matrix[x1 - 1][y1 - 1] << " " << matrix[x1 - 1][y2] << " "
// << matrix[x2][y1 - 1] << endl;
cout << matrix[x2][y2] + matrix[x1 - 1][y1 - 1] - matrix[x1 - 1][y2] - matrix[x2][y1 - 1] << "\n";
}
}
return 0;
}