5/5
果然上一篇博文是个flag啊!我果然拖更了!昨天的CF完了还没有更新上一次的CF题解,所以昨天差点GG(不过第三题这个分数也离GG不远了,好在rating没掉(/▽╲))。为了攒回人品,于是我马上更新啦……
题A A Good Contest
题意:给你人名,让你找rating是红名的,并且在比赛中有涨的~~
题解:这也太水了吧!这一点坑点都没啊,div2也不带这么水的~~
1 /*zhen hao*/
2 #include <bits/stdc++.h>
3 using namespace std;
4
5 #define lson l, m, rt*2
6 #define rson m + 1, r, rt*2+1
7 #define xx first
8 #define yy second
9
10 typedef pair<int,int> pii;
11 typedef long long ll;
12 typedef unsigned long long ull;
13
14 int main() {
15 // freopen("case.in", "r", stdin);
16 string id;
17 int before, after, n, ok = 0;
18 cin >> n;
19 for (int i = 0; i < n; i++) {
20 cin >> id >> before >> after;
21 if (before >= 2400 && after - before > 0) ok = 1;
22 }
23 puts(ok ? "YES" : "NO");
24 return 0;
25 }
题B Economy Game
题意:给你一个数,问你存不存在a、b、c使得a * 1234567 + b * 123456 + c * 1234 = n?
题解:显然枚举a和b得到c。
1 /*zhen hao*/
2 #include <bits/stdc++.h>
3 using namespace std;
4
5 #define lson l, m, rt*2
6 #define rson m + 1, r, rt*2+1
7 #define xx first
8 #define yy second
9
10 typedef pair<int,int> pii;
11 typedef long long ll;
12 typedef unsigned long long ull;
13
14 int main() {
15 // freopen("case.in", "r", stdin);
16 ll x = 1234567, y = 123456, z = 1234;
17 ll n;
18 cin >> n;
19 bool ok = false;
20 for (int i = 0; i * x <= n; i++) {
21 for (int j = 0; ; j++) {
22 if (x * i + y * j > n) break;
23 if ((n - x * i - y * j) % z == 0) ok = 1;
24 }
25 }
26 if (ok) puts("YES"); else puts("NO");
27 return 0;
28 }
题C Heap Operations
题意:给你一些堆操作,但这是不完全的,可能有漏的,你需要补漏,也就是加上最少的操作使得整个操作序列合法。
题解:我们用一个优先队列来维护,
a、insert就直接push进去;
b、getMin的话,分两种情况:1、队列为空,那么插入一个数即可,2、不空即看最开头的元素,如果小于x的话就pop出来(记得加操作),循环知道队列为空或者最开头的元素大于等于x,如果大于或者为空的话就要先insert一个x;
c、removeMin的话,要注意的是队列为空的时候没得remove,这时候就要随便加一个元素进去;
(最后注意一下优先队列的优先级,蒟蒻因为优先队列优先级忘了耽误了下一题的时间)
1 /*zhen hao*/
2 #include <bits/stdc++.h>
3 using namespace std;
4
5 #define lson l, m, rt*2
6 #define rson m + 1, r, rt*2+1
7 #define xx first
8 #define yy second
9
10 typedef pair<int,int> pii;
11 typedef long long ll;
12 typedef unsigned long long ull;
13
14 const int maxn = 2e5 + 100, maxm = 2e6 + 100;
15 int e, head[maxn];
16 char s[40];
17
18 struct Edge {
19 int v, op, nx;
20 } edges[maxm];
21
22 void init() {
23 e = 0;
24 memset(head, -1, sizeof head);
25 }
26
27 void add_edge(int u, int v, int op) {
28 edges[e].v = v;
29 edges[e].op = op;
30 edges[e].nx = head[u];
31 head[u] = e++;
32 }
33
34 int get_op() {
35 if (s[0] == 'i') return 0;
36 else if (s[0] == 'g') return 1;
37 else return 2;
38 }
39
40 vector<pii> p;
41
42 int main() {
43 // freopen("case.in", "r", stdin);
44 int n, v;
45 cin >> n;
46 init();
47 priority_queue<int, vector<int>, greater<int> > pq;
48 for (int i = 0; i < n; i++) {
49 scanf("%s", s);
50 int op = get_op();
51 if (op == 0 || op == 1) scanf("%d", &v);
52 // cout << op << ' ' << v << endl;
53 if (op == 0) pq.push(v);
54 else if (op == 2) {
55 if (pq.empty()) add_edge(i, 0, 0);
56 else pq.pop();
57 }
58 else {
59 if (pq.empty()) {
60 add_edge(i, v, 0);
61 pq.push(v);
62 } else {
63 while (!pq.empty() && pq.top() < v) {
64 add_edge(i, 0, 2);
65 pq.pop();
66 }
67 if (pq.empty() || pq.top() > v) {
68 add_edge(i, v, 0);
69 pq.push(v);
70 }
71 }
72 }
73 add_edge(i, v, op);
74 }
75 printf("%d
", e);
76 for (int u = 0; u < n; u++) {
77 p.clear();
78 for (int j = head[u]; ~j; j = edges[j].nx) {
79 p.push_back(make_pair(edges[j].op, edges[j].v));
80 }
81 for (int j = p.size() - 1; j >= 0; j--) {
82 int x = p[j].xx, y = p[j].yy;
83 if (x == 0) printf("%s %d
", "insert", y);
84 else if (x == 1) printf("%s %d
", "getMin", y);
85 else printf("%s
", "removeMin");
86 }
87 }
88 return 0;
89 }
题D Gifts by the List
题意:有n个人送礼,m对祖先关系,然后a必须送礼物给它的祖先(自己可以是自己的祖先),给出每个人想要送礼的人的编号,然后问你有没有一个安排,使得满足所有人的送礼,每个人会在安排中找第一个祖先来送礼物。
题解:首先要明确的是哪个安排一定是所有列出名单的人的集合,因为如果少一个人就会不满足哪个人的送礼物要求。现在分析一个,假设a想送给b,然后c是在a和b之间的,他想送个d,这个时候d只能是b才能满足,更具体点就是想送给b的人最底下的假设是a,那么a和b之间的所有人都必须送的是b,否则不可以。然后我们就可以得出一个解法:对于dfs序的x如果是想送礼物的名单,那么他的子树的所有没有送礼物的送礼物对象一定是x,所以这就变成了一个模拟题:先得出dfs序,对于一个点x(在送礼物名单中),把所有没有安排的人的并且是x的儿子的要送的人设为x,然后看是否和题目给出的人相吻合即可。
1 /*zhen hao*/
2 #include <bits/stdc++.h>
3 using namespace std;
4
5 #define lson l, m, rt*2
6 #define rson m + 1, r, rt*2+1
7 #define xx first
8 #define yy second
9
10 typedef pair<int,int> pii;
11 typedef long long ll;
12 typedef unsigned long long ull;
13
14 const int maxn = 1e5 + 10;
15 vector<int> son[maxn], topo, ans;
16 int a[maxn], b[maxn], is[maxn], vis[maxn];
17
18 void dfs(int u) {
19 vis[u] = 1;
20 for (int i = 0; i < (int)son[u].size(); i++) {
21 int v = son[u][i];
22 if (!vis[v]) dfs(v);
23 }
24 topo.push_back(u);
25 }
26
27 void dfs(int u, int p) {
28 if (b[u]) return;
29 b[u] = p;
30 for (int i = 0; i < (int)son[u].size(); i++) {
31 int v = son[u][i];
32 dfs(v, p);
33 }
34 }
35
36 int main() {
37 // freopen("case.in", "r", stdin);
38 int n, m;
39 cin >> n >> m;
40 for (int i = 0; i < m; i++) {
41 int u, v;
42 scanf("%d%d", &u, &v);
43 son[u].push_back(v);
44 }
45 for (int i = 1; i <= n; i++) {
46 scanf("%d", a + i);
47 is[a[i]] = 1;
48 }
49 memset(vis, 0, sizeof vis);
50 for (int i = 1; i <= n; i++) if (!vis[i]) dfs(i);
51 // for (int i = 0; i < (int)topo.size(); i++) cout << topo[i] << endl;
52 for (int i = 0; i < (int)topo.size(); i++) {
53 int u = topo[i];
54 if (is[u]) { dfs(u, u); ans.push_back(u); }
55 }
56 for (int i = 1; i <= n; i++) if (a[i] != b[i]) {
57 puts("-1"); return 0;
58 }
59 cout << ans.size() << endl;
60 for (int i = 0; i < (int)ans.size(); i++)
61 cout << ans[i] << endl;
62 return 0;
63 }
题E Runaway to a Shadow
题意:给你一个起始点(x0,y0),然后在时间T内以v的速度逃跑,随机往每个角度跑,当跑到给定圆的边界或园内则安全,问你这个逃跑成功的概率。
题解:这道题我觉得比上一题还要水,思路很容易。
1、如果在某个圆内,就输出1
2、对于每个圆求出角度的范围[angL,angR];(要用到余弦定理)
3、然后把每个区间塞到vector里面去,取区间的并集在除以2 * pi则为答案。
怎么取区间的并集?
把每个区间放到vector,并注明左边界是1,右边界是-1,然后排序之后取出来加起来即可!!这道题应该主要是怎么区间取并吧,学到新姿势了orz!
1 /*zhen hao*/
2 #include <bits/stdc++.h>
3 using namespace std;
4
5 const double eps = 1e-9, PI = acos(-1.0);
6
7 vector<pair<double,int> > p;
8
9 double dist(double x1, double y1, double x2, double y2) {
10 return 1.0 * (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
11 }
12
13 int main() {
14 // freopen("case.in", "r", stdin);
15 int x0, y0, v, t, n;
16 cin >> x0 >> y0 >> v >> t >> n;
17 double r0 = 1.0 * v * t;
18 for (int i = 0; i < n; i++) {
19 int x, y, r;
20 scanf("%d%d%d", &x, &y, &r);
21
22 double d = dist(x, y, x0, y0), sd = sqrt(d);
23 if (d < 1.0 * r * r + eps) {
24 puts("1.000000000"); return 0;
25 }
26
27 if (r + r0 < sd - eps) continue;
28
29 double dr = sqrt(d - 1.0 * r * r);
30 double ang, angL, angR, angM = atan2(y - y0, x - x0);
31
32 if (angM < 0) angM += 2 * PI;
33
34 if (dr < r0 + eps) {
35 ang = asin(r / sd);
36 }
37 else {
38 ang = acos((d + r0 * r0 - 1.0 * r * r) / (2.0 * sd * r0));
39 }
40
41 angL = angM - ang;
42 angR = angM + ang;
43
44 if (angL < 0) {
45 p.push_back(make_pair(angL + 2 * PI, 1));
46 p.push_back(make_pair(2 * PI, -1));
47 p.push_back(make_pair(0.0, 1));
48 p.push_back(make_pair(angR, -1));
49 }
50 else if (angR > 2 * PI) {
51 p.push_back(make_pair(angL, 1));
52 p.push_back(make_pair(2 * PI, -1));
53 p.push_back(make_pair(0.0, 1));
54 p.push_back(make_pair(angR - 2 * PI, -1));
55 }
56 else {
57 p.push_back(make_pair(angL, 1));
58 p.push_back(make_pair(angR, -1));
59 }
60 }
61 sort(p.begin(), p.end());
62 int sum = 0;
63 double pre = 0, ans = 0;
64 for (int i = 0; i < (int)p.size(); i++) {
65 if (sum > 0) ans += p[i].first - pre;
66 sum += p[i].second;
67 pre = p[i].first;
68 }
69 printf("%.10lf
", ans / (2.0 * PI));
70 }