Educational Round #10 — Editorial
The paddle trick performs the following permutation of the loaves:
It can be represented as two swaps of adjacent elements:
Each swap of adjacent elements changes the parity of the permutation. Therefore, this operation on the loaves preserves the parity of the permutation.
It is possible to sort the loaves in the order required by Michael's boss only if the parities of the permutations coincide.
A linear solution to the problem is based on the fact that two permutations have the same parity if and only if the parity of the number of cycles in their decompositions is the same.
Lemma. Consider the following fact from permutation theory:
Therefore, to check the parity one can:
decompose the permutation into cycles;
count the number of cycles.
If two permutations have the same parity of the number of cycles, then their permutation parities coincide.
Intuitively, this follows from the fact that each cycle of length can be constructed from swaps of elements; therefore, the total number of swaps is equal to
Example
In the first example, the first permutation contains inversions, while the second contains inversions. The number of inversions in both permutations has the same parity.
Let us decompose the permutations into cycles:
;
;
Both permutations consist of two cycles; therefore, the number of cycles in them also has the same parity.
In the second example, the first permutation contains inversions, while the second contains inversions. The number of inversions in these permutations has different parity.
Let us decompose the permutations into cycles:
;
;
The first permutation consists of cycles, while the second consists of cycles. Thus, the parity of the number of cycles in these permutations is different.
Declare an array to store the permutation.
#define MAX 100010 int a[MAX];
The function run traverses one cycle of the permutation starting from index . At each step, it moves to the next element of the cycle according to the rule . Visited elements are marked with the value to avoid processing them again. Thus, the function completely traverses one cycle of the permutation and marks all its elements as already visited.
void run(int pos)
{
int v;
while (a[pos] != -1)
{
v = a[pos];
a[pos] = -1;
pos = v;
}
}The function parity computes the parity of the number of cycles in the permutation , that is, it returns the number of cycles modulo . The function sequentially scans all positions of the array.
int parity(int *a)
{
int res = 0;Sequentially examine all positions of the array.
for (int i = 0; i < n; i++)
If an element has not yet been visited , this means the beginning of a new cycle. In this case, the function is called, which traverses the entire cycle and marks its elements with the value .
if (a[i] != -1)
{
run(i);After traversing the cycle, the counter is increased by .
res++;
}Return the parity of the number of cycles.
return res % 2; }
The main part of the program. Read the first permutation. During input, each value is decreased by to convert from -based indexing to the more convenient -based indexing .
scanf("%d",&n);
for (i = 0; i < n; i++)
scanf("%d",&a[i]), a[i]--;In the variable , compute the parity of the number of cycles in the permutation .
p1 = parity(a);
Read the second permutation. In the variable , compute the parity of the number of cycles in the permutation .
for (i = 0; i < n; i++)
scanf("%d",&a[i]), a[i]--;
p2 = parity(a);Compare the parities of the number of cycles in the two permutations and print the result.
if (p1 == p2) printf("Possible\n");
else printf("Impossible\n");"Theodore Roosevelt" — the flagship of the Kukuland fleet. The sworn enemies of Kukuland, the Flat-Earthers, decided to destroy it. They learned that "Theodore Roosevelt" is represented by a convex polygon with vertices, and the coordinates of all its vertices are known to them. Then they launched ballistic missiles and recorded the coordinates of their explosion points. According to the calculations of the Flat-Earthers' headquarters, "Theodore Roosevelt" will be destroyed if at least missiles hit it. Determine whether the Flat-Earthers managed to destroy the ship.
Input. The first line contains integers and . The next lines contain the coordinates of the polygon vertices in counterclockwise order. The following lines contain the coordinates of the explosion points. All coordinates are integers with absolute values not exceeding .
Output. Print "YES" if at least points lie inside the polygon, and "NO" otherwise.
5 4 2 1 -1 1 2 0 4 -1 2 -1 -1 -2 -1 1 -1 0 1 2 3
YES
Consider the problem of determining whether a point belongs to a convex polygon.
Suppose the vertices of the polygon are given in counterclockwise order: . Fix the vertex . Then all other vertices are ordered around it by polar angle.
Draw rays from point through the remaining vertices (i.e., the diagonals of the polygon). We can now apply binary search to find an edge such that the orientations of the triples of points and are different.
Thus, we determine the sector (triangle) in which the point may lie.
After the angle containing the point is found, we can check in constant time whether the points and lie on the same side of the line . For this, the orientation of the triple must be left (since the orientation of is left, as the polygon vertices are given in counterclockwise order).
At the beginning of the algorithm, it is also necessary to check boundary cases: if the orientation of the triple is left or the orientation of the triple is right, then the point lies outside the polygon.
Turn direction. Consider moving from point to point , and then from to point . The turn is considered left (counterclockwise) if the vector (pseudo-scalar) product , and right if .
Let us define a structure and an array of points.
#define MAX 100001
struct Point
{
long long x, y;
Point(long long x = 0, long long y = 0) : x(x), y(y) {}
};
Point p[MAX];The function angle determines whether the turn made when moving through points is left or right. To do this, we calculate the corresponding vectors:
The pseudo-scalar (cross) product of is
The sign of this expression determines the direction of the turn:
Positive value — left turn;
Negative value — right turn;
int angle(Point a, Point b, Point c)
{
long long q = (b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x);
return (q > 0) - (q < 0); // sgn(q)
}The function inside returns if the point lies inside the polygon.
bool inside(Point q)
{We choose the first vertex of the polygon as the base.
Point a = p[1];
If the orientation of the triple is left, or the orientation of the triple is right, then the point lies outside the angle , and therefore outside the polygon.
if (angle(a, p[2], q) < 0 || angle(a, p[n], q) > 0) return false;
Perform a binary search on the interval . We look for points and such that the point lies inside the angle .
int l = 2, r = n, m;
while (l + 1 < r)
{
m = (l + r) / 2;
if (angle(a, p[m], q) < 0)
r = m;
else
l = m;
}
return angle(p[l], p[r], q) >= 0;
}The main part of the program. Read the input data.
scanf("%d %d %d", &n, &m, &k);
for (int i = 1; i <= n; i++)
{
scanf("%lld %lld", &x, &y);
p[i] = Point(x, y);
}Compute the number of points that lie inside the polygon.
res = 0;
for (int i = 1; i <= m; ++i)
{
scanf("%lld %lld", &x, &y);
if (inside(Point(x, y))) res++;
}Print the answer.
if (res < k) puts("NO"); else puts("YES");Farmer John has arrived in the city with his cows! During sunset, the cows look at the city skyline and observe beautiful silhouettes formed by rectangular buildings.
The entire skyline is represented by a number line with buildings. The silhouette of the -th building extends along the horizon between points and and has height . Determine the total area (in square units) of the silhouette formed by all buildings.
Input. The first line contains an integer . Each of the next lines describes the -th building with three integers: and .
Output. Print the total area of the city skyline (in square units) formed by all buildings.

4 2 5 1 9 10 4 6 8 2 4 6 3
16
Consider all points — the -coordinates of the beginnings and ends of the buildings — and sort them in increasing order. For each such point, we store:
its coordinate,
its type (start of a building — , end — ),
the height of the corresponding building.
Next, process these points sequentially from left to right.
We maintain a multiset that stores the heights of buildings that have already started but have not yet ended at the current moment. This multiset allows us to efficiently determine the maximum height among the active buildings.
Let the current point have coordinate , and the next point . Let denote the maximum element in the multiset (if the set is empty, assume ). Then, on the interval ), the maximum height of the silhouette is , and the contribution to the area is
Add this value to the total area.
After that, update the multiset:
if the point is the start of a building, insert its height into ;
if it is the end of a building, we remove the corresponding height from .
The order of processing events with the same -coordinate (starts and ends of buildings) does not affect the correctness of the solution, since segments of zero length do not contribute to the area.
Example
To represent a point, we introduce a structure that stores its -coordinate, a flag indicating whether it is the start () or the end () of a segment, and the height of the corresponding building.
struct node
{
int x, type, h;
node(int x, int type, int h) : x(x), type(type), h(h) {};
};Define a comparator f for points — sort them in increasing order of their -coordinates.
int f(node a, node b)
{
return a.x < b.x;
}Declare an array of points , as well as a multiset to store the heights of buildings intersecting the current position of the sweep line.
vector<node> Event; multiset<int, greater<int> > s;
Read the input data. Construct the array of points.
scanf("%d",&n);
for(i = 0; i < n; i++)
{
scanf("%d %d %d",&left,&right,&height);
Event.push_back(node(left,0,height));
Event.push_back(node(right,1,height));
}Sort the array of points in non-decreasing order of their -coordinates.
sort(Event.begin(),Event.end(),f);
Accumulate the total area of the city skyline in the variable .
res = 0;
Move from left to right over the points in the array. For each index in the loop, consider the interval .
for (i = 0; i < Event.size() - 1; i++)
{If the point is the start of a building, insert the corresponding height into the multiset.
int h = Event[i].h; if (Event[i].type == 0) s.insert(h);
If the point is the end of a building, remove the corresponding height from the multiset.
else s.erase(s.find(h));
If the multiset is not empty, then on the segment between and there exists a skyline whose height is equal to the maximum element in , i.e. .
if (!s.empty())
res += 1LL * *s.begin() * (Event[i+1].x - Event[i].x);
}Print the computed area.
printf("%lld\n",res);