Wizards' Duel
题目链接:
http://codeforces.com/problemset/problem/591/A
解题思路:
Let's start with determining the position of the first collision. Two impulses converge with a speed p + q, so the first collision will occur after seconds. The coordinate of this collision is given by the formula
.
Note, that the distance one impulse passes while returning to it's caster is equal to the distance it has passed from the caster to the first collision. That means impulses will reach their casters simultaneously, and the situation will be identic to the beginning of the duel. Hence, the second collision (third, fourth, etc) will occur at exactly the same place as the first one.
题目大意:
把问题简化成为:两物体相向而行,问相遇的地点(相对于第一个物体而言)。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main(){
double l,p,q;
while(~scanf("%lf%lf%lf",&l,&p,&q)){
printf("%.4lf\n",l/(p+q)*p);
}
return 0;
}
Rebranding
题目链接:
http://codeforces.com/problemset/problem/590/B
解题思路:
Trivial solution will just emulate the work of all designers, every time considering all characters of the string one by one and replacing all xiwith yi and vice versa. This will work in O(n·m) and get TL.
First one should note that same characters always end as a same characters, meaning the position of the letter doesn't affect the result in any way. One should only remember the mapping for all distinct characters. Let p(i, c) be the mapping of c after i designers already finished their job. Now:
- p(0, c) = c
- If p(i - 1, c) = xi, then p(i, c) = yi
- Same, if p(i - 1, c) = yi, then p(i, c) = xi
This solution complexity is O(|Σ|·m + n) and is enough to pass all the tests.
Challenge: improve the complexity to O(Σ + n + m).
题目大意:输入n和m, 然后再输入n个字母。再给你m个替换操作,输出替换后的字符串。
算法思想:
不能直接操作,考虑到英文小写英文字母最多只有26个,直接对26个英文字母进行替换操作,然后再带进去即可。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char str[200005],change[30];
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
scanf("%s",str);
char x,y,tmp;
for(int i = 0; i < 26; i++)
change[i] = i+'a';
for(int i = 0; i < m; i++){
getchar();
scanf("%c%c%c",&x,&tmp,&y);
for(int j = 0; j < 26; j++){
if(change[j] == x)
change[j] = y;
else if(change[j] == y)
change[j] = x;
}
}
for(int i = 0; i < n; i++)
str[i] = change[str[i]-'a'];
printf("%s\n",str);
}
return 0;
}
Median Smoothing(找规律)
题目链接:
http://codeforces.com/problemset/problem/590/A
解题思路:
We will call the element of a sequence stable, if it doesn't change after applying the algorithm of median smoothing for any number of times. Both ends are stable by the definition of the median smoothing. Also, it is easy to notice, that two equal consecutive elements are both stable.
Now we should take a look at how do stable elements affect their neighbors. Suppose ai - 1 = ai, meaning i - 1 and i are stable. Additionaly assume, that ai + 1 is not a stable element, hence ai + 1 ≠ ai and ai + 1 ≠ ai + 2. Keeping in mind that only 0 and 1 values are possible, we conclude that ai = ai + 2 and applying a median smoothing algorithm to this sequence will result in ai = ai + 1. That means, if there is a stable element in position i, both i + 1 and i - 1 are guaranteed to be stable after one application of median smoothing. Now we can conclude, that all sequences will turn to stable at some point.
Note, that if there are two stable elements i and j with no other stable elements located between them, the sequence of elements between them is alternating, i.e. ak = (ai + k - i)mod2, where . One can check, that stable elements may occur only at the ends of the alternating sequence, meaning the sequence will remain alternating until it will be killed by effect spreading from ending stable elements.
The solution is: calculate max(min(|i - sj|)), where sj are the initial stable elements. Time complexity is O(n).
Challenge 1: hack the solution that just applies median smoothing until something changes.
Challenge 2: think of how to speed up the algorithm from challenge 1 using bitmasks (still gets TL).
题目大意:给你了一段 0 1 组成的波,然后这个波的值可能会发生变化,不计起点和终点,如果某一位置上的值不等于其左右位置加上自己的中位数话,那么它会变成中位数,这样导致波会振荡一次,问波最终是否会稳定,不会输出-1。会,就输出其振荡次数与最终波的值。
算法思想:
首先可以判断最终波是一定会稳定的,不可能最终不稳定。因为只有0与1,边缘值a1与an不变了,所以他们只会往中间延伸这种稳定的状态。然后确定只要连着两个00 或者11 就不会改变,改变的只会是01交替出现的。然后不断更新即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 505050;
int n;
int arr[maxn];
int modify(int l, int r){
if(l == r)
return 0;
if(arr[l] == arr[r]){
for(int i = l+1; i < r; i++)
arr[i] = arr[l];
return (r-l)/2;
}
else{
int m = (l+r+1)/2;
for(int i = l+1; i < m; i++)
arr[i] = arr[l];
for(int i = m; i < r; i++)
arr[i] = arr[r];
return (r-l-1)/2;
}
}
int main(){
while(~scanf("%d",&n)){
for(int i = 0; i < n; i++)
scanf("%d",&arr[i]);
int ans = 0;
int l = 0;
for(int i = 0; i < n; i++){
if(i == n-1 || arr[i] == arr[i+1]){
ans = max(ans, modify(l, i));
l = i+1;
}
}
printf("%d\n",ans);
for(int i = 0; i < n-1; i++)
printf("%d ",arr[i]);
printf("%d\n",arr[n-1]);
}
return 0;
}
Chip 'n Dale Rescue Rangers(二分)
题目链接:
http://codeforces.com/problemset/problem/590/B
解题思路:
If the velocity of the dirigible relative to the air is given by the vector (ax, ay), while the velocity of the wind is (bx, by), the resulting velocity of the dirigible relative to the plane is (ax + bx, ay + by).
The main idea here is that the answer function is monotonous. If the dirigible is able to reach to target in seconds, then it can do so in
seconds, for any x ≥ 0. That is an obvious consequence from the fact the maximum self speed of the dirigible is strictly greater then the speed of the wind at any moment of time.
For any monotonous function we can use binary search. Now we only need to check, if for some given value it's possible for the dirigible to reach the target in
seconds. Let's separate the movement of the air and the movement of the dirigible in the air. The movement cause by the air is:
- (xn, yn) =
, if
;
- (xn, yn) =
, for
.
The only thing we need to check now is that the distance between the point (xn, yn) and the target coordinates (x2, y2) can be covered moving with the speed vmax in seconds assuming there is no wind.
Time complexity is , where C stands for the maximum coordinate, аnd ε — desired accuracy.
Challenge 1: think of the solution in case it's not guaranteed that the dirigible is faster than the wind.
Challenge 2: can you come up with O(1) solution?
物理问题,求飞船从一点到另一点的距离,有风速的影响。orz,我当时怎么没想到呢,这题居然用二分,把飞船和风分开考虑,不然不断二分求解。太好了。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
double x1,y1,x2,y2,vmax,t,vx,vy,wx,wy;
while(~scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2)){
scanf("%lf%lf",&vmax,&t);
scanf("%lf%lf%lf%lf",&vx,&vy,&wx,&wy);
double l = 0, r = 1e9;
for(int i = 0; i < 100; i++){
double mid = (l+r)/2;
double x = x1 + min(mid, t) * vx + max(mid - t, 0.0) * wx;
double y = y1 + min(mid, t) * vy + max(mid - t, 0.0) * wy;
(hypot(x - x2, y - y2) > vmax * mid ? l : r) = mid;
//hypot计算直角三角形的斜边长
}
printf("%.6lf\n",l);
}
return 0;
}