#P7881. Semigroup Grid Updates and Queries
Semigroup Grid Updates and Queries
Semigroup Grid Updates and Queries
In this problem, every point (x,y) on an infinite 2D plane has an associated weight d(x,y) which is an element of a semigroup \((D, *, e)\). The type Data
represents an element in \(D\) and is defined as follows:
struct Data{
unsigned short a, b, c, d;
void operator*=(const Data &x);
void clr();
};
The operation *=
satisfies the associativity property:
\[
x*(y*z) = (x*y)*z, \quad \forall x,y,z\in D.
\]
There is an identity element \(e\) (which can be set by calling clr()
on a Data
object) such that for every \(x\in D\),
\[
x*e = e*x = x.
\]
You are required to implement the following functions (do not include the header lib.h
when you submit):
/* BEGIN HEADER: */
struct Data{
unsigned short a, b, c, d;
void operator*=(const Data &x);
void clr();
};
void update(int x, int dim, Data d1, Data d2);
Data query(int x, int y);
/* END HEADER. */
// Please complete the following template.
#include
// Global storage for update operations
struct Operation {
int thresh; // parameter x (threshold)
int dim; // 0 means update by x-coordinate; 1 means update by y-coordinate
Data d1, d2; // d1 used if coordinate less than thresh, d2 used otherwise
};
static std::vector ops;
// We define the semigroup operation as component-wise addition modulo 65536.
// Identity element e is (0,0,0,0).
void Data::operator*=(const Data &x) {
a = (unsigned short)((a + x.a) & 0xFFFF);
b = (unsigned short)((b + x.b) & 0xFFFF);
c = (unsigned short)((c + x.c) & 0xFFFF);
d = (unsigned short)((d + x.d) & 0xFFFF);
}
void Data::clr() {
a = b = c = d = 0;
}
// update applies an update over all points in the plane.
// If dim == 0 then for every point (x0, y0):
// if x0 < x then d(x0, y0) = d(x0, y0) * d1
// else d(x0, y0) = d(x0, y0) * d2
// If dim == 1 then for every point (x0, y0):
// if y0 < x then d(x0, y0) = d(x0, y0) * d1
// else d(x0, y0) = d(x0, y0) * d2
void update(int x, int dim, Data d1, Data d2) {
Operation op;
op.thresh = x;
op.dim = dim;
op.d1 = d1;
op.d2 = d2;
ops.push_back(op);
}
// query returns the current weight at point (x, y), computed as the sequentially applied updates
Data query(int x, int y) {
Data ans;
ans.clr(); // initialize to identity e = (0,0,0,0)
// Apply each update in the order they were called
for (auto &op : ops) {
if (op.dim == 0) {
if (x < op.thresh) {
ans *= op.d1;
} else {
ans *= op.d2;
}
} else {
if (y > Q;
for(int i=0; i> op_type;
if(op_type == 1){
int x, dim;
std::cin >> x >> dim;
Data d1, d2;
std::cin >> d1.a >> d1.b >> d1.c >> d1.d;
std::cin >> d2.a >> d2.b >> d2.c >> d2.d;
update(x, dim, d1, d2);
} else {
int x, y;
std::cin >> x >> y;
Data res = query(x, y);
std::cout << res.a << " " << res.b << " " << res.c << " " << res.d << std::endl;
}
}
return 0;
}
## inputFormat
The first line contains an integer Q
representing the number of operations. Each of the following Q
lines is either an update or a query operation.
- An update operation is in the format:
1 x dim d1.a d1.b d1.c d1.d d2.a d2.b d2.c d2.d
- A query operation is in the format:
2 x y
It is guaranteed that there will be at least one update and one query operation.
## outputFormat
For each query operation, output a single line with four unsigned short numbers representing Data a, b, c, d
after applying all the updates in order.
## sample
3
2 10 20
1 15 0 1 2 3 4 10 20 30 40
2 10 100
0 0 0 0
1 2 3 4
</p>