Wizmann / ACM-ICPC

感觉自己做了假题。
http://wizmann.tk
Other
63 stars 29 forks source link

AtCoder Beginner Contest 165 #22

Closed Wizmann closed 4 years ago

Wizmann commented 4 years ago

Contest Code

我是傻逼。

E. Rotation Matching

题意

N个人编号1,2,3...N,两两比赛。 有M个比赛场地,每个比赛场地指定一组编号(a, b)。即编号为a和b的人在该场地进行一轮比赛。

每一轮比赛完成后,所有人的编号x都变为(x % N + 1)。问如何给场地进行编号,使得一个人在一轮比赛最多出场1次(可以不出场)。并且在N轮比赛中,不会有重复的对战。

看不懂描述可以去看原题,题意挺绕的。

解法

首先要看懂题。然后会有一个基本的想法:因为人与人之间的编号差值不会改变,所以每一个差值最多只能出现一次。

然后手写一下N=4,M=1的情况:

1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3

我们可以看到,选择(1, 2)和(1, 4)是可行的,但是(1, 3)不可行。(1, 2), (1, 4)的差值为1和3,(1, 3)差值为2。并且(1, 2)和(1, 4)不能同时出现。 这时就要修正上面的想法。第一,两人编号的差值有两个: |b - a| 和 |a - b + n|。这两个差值都不能重复。第二,|b - a| <= (n - 1) / 2,否则就会发生(a, b)和(b, a)两轮比赛的重复。 也就是说,对于N个人,我们最多能同时进行(N - 1) / 2场比赛,每场比赛(a, b)编号差分别为[1... (N - 1) / 2]。

现在的问题就变成了怎么样来着构造适当的(a,b)编号了。 假设我们从(x, x+1)开始向两边扩展,就可以构造出差为1,3,5..的场地。因为差值最大不能超过(n - 1) / 2,所以只会用掉一半的编号。另外一半我们从(x, x + 2)进行扩展,构造差值为2,4,5..的场地。

F. LIS on Tree

题意

给定一颗有根树,树的每一个节点都有一个值。问从根到叶子的路径中,最长上升子序列有多长。

解法

这题比较有新意,但是并不难。

使用栈+二分的方法求LIS应该是非常常见的。在树上做的问题在于怎么样维护这个栈。 因为栈在状态转移过程中可能会修改中间的值或者在后面插入值。所以我们在dfs的每一层记录下当前的操作,在返回上一层的时候恢复回来即可。

可以写一个类似回调的东西骚一下。