Skip to content

Commit 70532bf

Browse files
Add files via upload
1 parent 0850c0c commit 70532bf

File tree

3 files changed

+248
-0
lines changed

3 files changed

+248
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
There is a crucial insight that we can make here.
2+
We can make a 'waiting' move.
3+
4+
After we travel from a -> b, we can keep going back and forth on the same edge.
5+
b-> c -> b
6+
7+
We can keep going back and forth to one of the neighbours of b.
8+
This way, we can make an unlimited number of moves !
9+
10+
----
11+
12+
Suppose we have a path of length L.
13+
There is a path of length (L + 2X) for every integer X.
14+
15+
----
16+
17+
Now, there are 3 Simple Paths from (a, b)
18+
19+
1. a -> b
20+
2. a -> x -> y -> b
21+
3. a -> y -> x -> b
22+
23+
----
24+
25+
If any of these path lengths <= k and have the same parity as k,
26+
then we can use the required number of waiting moves to go from (a, b) and
27+
use exactly k moves.
28+
29+
----
30+
31+
We can use LCA to calculate the distance between 2 vertices.
32+
We can do O(N Log N) precompute and answer each query in O(Log N) time.
33+
34+
-----
35+
36+
int main()
37+
{
38+
int no_of_vertices;
39+
cin >> no_of_vertices;
40+
41+
int no_of_edges = no_of_vertices - 1;
42+
for(int i = 1; i <= no_of_edges; i++)
43+
{
44+
int u, v;
45+
cin >> u >> v;
46+
47+
tree[u].push_back(v);
48+
tree[v].push_back(u);
49+
}
50+
51+
depth[0] = 0;
52+
53+
dfs(1, 0);
54+
55+
precompute_parents(no_of_vertices);
56+
57+
int no_of_queries;
58+
cin >> no_of_queries;
59+
60+
for(int i = 1; i <= no_of_queries; i++)
61+
{
62+
int x, y, a, b, k;
63+
cin >> x >> y >> a >> b >> k;
64+
65+
int path_1 = distance(a, b);
66+
int path_2 = distance(a, x) + distance(b, y) + 1;
67+
int path_3 = distance(a, y) + distance(b, x) + 1;
68+
69+
if( (path_1 <= k && path_1%2 == k%2) ||
70+
(path_2 <= k && path_2%2 == k%2) ||
71+
(path_3 <= k && path_3%2 == k%2) )
72+
{
73+
cout << "YES\n";
74+
}
75+
else
76+
{
77+
cout << "NO\n";
78+
}
79+
}
80+
81+
return 0;
82+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
We can interpret this problem geometrically and it would help greatly.
2+
3+
Let us visualise the time on the y-axis and the temperature on the x axis.
4+
We are given a set of segments and we must determine if it is possible to draw
5+
a line that passes through each of them.
6+
7+
Instead of keeping track of a line, we will keep track of the possible range of the line.
8+
Let the line always lie between [A, B] on the x axis.
9+
10+
In the time between two events, the minimum can reduce by at most (T[i] - T[i - 1])
11+
and the maximum can reduce by at most (T[i] - T[i - 1])
12+
13+
However, we have to be careful of one thing.
14+
15+
The minimum range of the line cannot be lesser than the Left boundary of any event.
16+
The maximum range of the line cannot be greater than the Right boundary of any event.
17+
18+
So at every point, we just have to update the minimum and maximum range of the line.
19+
We are keeping the range as large as possible at every step.
20+
If a line exists, it has to do so within this range.
21+
22+
The beauty of this approach is that we don't have to find the actual line. Just knowing it's range is enough. :)
23+
24+
-----
25+
26+
struct customer
27+
{
28+
int time, left, right;
29+
30+
customer(){}
31+
32+
customer(int T, int L, int R)
33+
{
34+
time = T; left = L; right = R;
35+
}
36+
};
37+
38+
int sort_by_time(customer &A, customer &B)
39+
{
40+
if(A.time == B.time)
41+
{
42+
return (A.left < B.left);
43+
}
44+
45+
return (A.time < B.time);
46+
}
47+
48+
void solve()
49+
{
50+
int no_of_customers, starting;
51+
cin >> no_of_customers >> starting;
52+
53+
vector <customer> C(no_of_customers, customer(0, 0, 0));
54+
for(int i = 0; i < no_of_customers; i++)
55+
{
56+
cin >> C[i].time >> C[i].left >> C[i].right;
57+
}
58+
59+
sort(all(C), sort_by_time);
60+
61+
int minimum = starting, maximum = starting;
62+
int possible = true;
63+
64+
for(int i = 0; i < no_of_customers && possible; i++)
65+
{
66+
if(i == 0)
67+
{
68+
minimum = starting - C[i].time;
69+
maximum = starting + C[i].time;
70+
}
71+
else
72+
{
73+
minimum = minimum - (C[i].time - C[i - 1].time);
74+
maximum = maximum + (C[i].time - C[i - 1].time);
75+
}
76+
77+
if(minimum > C[i].right || maximum < C[i].left)
78+
{
79+
possible = false;
80+
break;
81+
}
82+
83+
minimum = max(minimum, C[i].left);
84+
maximum = min(maximum, C[i].right);
85+
}
86+
87+
cout << (possible ? "YES\n" : "NO\n");
88+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
Let R[S] be the reverse of string S
2+
3+
The final palindrome looks like this
4+
5+
S1 S2 S3 ... Sm (M)R[Sm] ... R[S3]R[S2]R[S1]
6+
And M is a palindrome that can be placed in the middle.
7+
8+
The constraints are small enough that we can check every pair of strings.
9+
For each string S[i], we will check if it's reverse R(S[i]) is also present in the array.
10+
We will store all the strings in one vector and all their reverses in another vector.
11+
12+
Suppose S[i] is the 3rd string in the list of strings we will print,
13+
then R(S[i]) is the 3rd last string that we need to print.
14+
15+
Lastly, we can have at most 1 palindromic string in the middle.
16+
We will check if any of the strings are palindromes.
17+
If they are, we will use one in the middle.
18+
19+
-----
20+
21+
int main()
22+
{
23+
int no_of_strings, length;
24+
cin >> no_of_strings >> length;
25+
26+
vector <string> S(no_of_strings + 1);
27+
for(int i = 1; i <= no_of_strings; i++)
28+
{
29+
cin >> S[i];
30+
}
31+
32+
vector <int> strings_index;
33+
vector <int> reverse_strings_index;
34+
for(int i = 1; i <= no_of_strings; i++)
35+
{
36+
for(int j = i + 1; j <= no_of_strings; j++)
37+
{
38+
if(is_palindrome(S[i] + S[j]))
39+
{
40+
strings_index.push_back(i);
41+
reverse_strings_index.push_back(j);
42+
}
43+
}
44+
}
45+
46+
string middle;
47+
for(int i = 1; i <= no_of_strings; i++)
48+
{
49+
if(is_palindrome(S[i]))
50+
{
51+
middle = S[i];
52+
}
53+
}
54+
55+
int final_length = strings_index.size() + (middle.size() != 0) + reverse_strings_index.size();
56+
57+
final_length *= length;
58+
59+
cout << final_length << "\n";
60+
61+
for(int i = 0; i < strings_index.size(); i++)
62+
{
63+
cout << S[strings_index[i]];
64+
}
65+
66+
if(middle.size() != 0)
67+
{
68+
cout << middle;
69+
}
70+
71+
for(int i = reverse_strings_index.size() - 1; i >= 0; i--)
72+
{
73+
cout << S[reverse_strings_index[i]];
74+
}
75+
76+
cout << "\n";
77+
return 0;
78+
}

0 commit comments

Comments
 (0)