第一题:小美玩排列
小美拿到了一个排列。她想知道在这个排列中,x和y是否是相邻的。你能帮帮她吗?排列是指一个长度为n的数组,其中 1 到n 每个元素恰好出现一次。
输入描述
第一行输入一个正整数n,代表排列的长度。
第二行输入n个正整数ai,代表排列的元素。
第三行输入两个正整数x和y,用空格隔开。
1 <= n <= 200000
1 <= ai, x,y <= n
保证 x != y
输出描述
如果x和y在排列中相邻,则输出"Yes"。否则输出"No"。
func neighbor(length int, nums []int, x, y int) bool {
for i := 0; i < length-1; i++ {
if nums[i] == x {
if nums[i+1] == y {
return true
}
}
if nums[i] == y {
if nums[i+1] == x {
return true
}
}
}
return false
}
func main() {
var length int
fmt.Scan(&length)
nums := make([]int, length)
for i := range nums {
fmt.Scan(&nums[i])
}
var x, y int
fmt.Scan(&x, &y)
fmt.Println(neighbor(length, nums, x, y))
}
第二题:小美走公路
有一个环形的公路,上面共有n站,现在给定了顺时针第i站到第i+1站之间的距离(特殊的,也给出了第n站到第1站的距离)。小美想沿着公路第x站走到第y站,她想知道最短的距离是多少?
输入描述
第一行输入一个正整数n,代表站的数量。第二行输入n个正整数ai,前n-1个数代表顺时针沿着公路走,i站到第i+1站之间的距离;最后一个正整数代表顺时针沿着公路走,第n站到第1站的距离。· 第三行输入两个正整数x和y,代表小美的出发地和目的地。
1 <= n <= 10^5
1 <= ai <= 10^9
1 <= x,y <= n
输出描述
一个正整数,代表小美走的最短距离。
func long(nums []int, x, y int) int {
if x == y {
return 0
}
if x > y {
x, y = y, x
}
var sum int
for _, i := range nums {
sum += i
}
var res int
for i := x; i < y; i++ {
res += nums[i]
}
return min(res, sum-res)
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
func main() {
var length int
fmt.Scan(&length)
nums := make([]int, length)
for i := range nums {
fmt.Scan(&nums[i])
}
var x, y int
fmt.Scan(&x, &y)
x--
y--
fmt.Println(long(nums, x, y))
}
第三题:小美切蛋糕
小美有一个矩形的蛋糕,共分成了n行m列,共n*m个区域,每个区域是一个小正方形,已知蛋糕每个区域都有一个美味度。她想切一刀把蛋糕切成两部分,自己吃一部分,小团吃另一部分。
小美希望两个人吃的部分的美味度之和尽可能接近,请你输出 |s1-s2|的最小值。(其中s1代表小美吃的美味度,s2代表小团吃的美味度)
请务必保证,切下来的区域都是完整的,即不能把某个小正方形切成两个小区域。
输入描述
第一行输出两个正整数n和m,代表蛋糕区域的行数和列数。
接下来的n行,每行输入m个正整数,用来表示每个区域的美味度。
1 <=n,m <=10^3
m个正整数均小于10^4
package main
import (
"fmt"
)
func cake(nums [][]int, x, y int) int {
xs := make([]int, x)
ys := make([]int, y)
sum := 0
now := 0
for i := 0; i < x; i++ {
for j := 0; j < y; j++ {
xs[i] += nums[i][j]
ys[j] += nums[i][j]
sum += nums[i][j]
}
}
res := sum
for i := 0; i < x; i++ {
now += xs[i]
res = min(abs(sum-now-now), res)
}
now = 0
for j := 0; j < y; j++ {
now += ys[j]
res = min(abs(sum-now-now), res)
}
return res
}
func abs(a int) int {
if a > 0 {
return a
}
return -a
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
func main() {
var x, y int
fmt.Scan(&x, &y)
cakeSum := make([][]int, x)
for i := range cakeSum {
cakeSum[i] = make([]int, y)
}
for i := range cakeSum {
for j := range cakeSum[i] {
fmt.Scan(&cakeSum[i][j])
}
}
fmt.Println(cake(cakeSum, x, y))
}
第四题:小美将字符串平铺成矩阵
小美拿到了一个长度为n的字符串,她希望将字符串从左到右平铺成一个矩阵(先平铺第一行,然后是第二行,以此类推,矩阵有x行y列,必须保证x*y=n,即每y个字符换行,共x行)。
该矩阵的权值定义为这个矩阵的连通块数量。小美希望最终矩阵的权值尽可能小,你能帮小美求出这个最小权值吗?
注:我们定义,上下左右四个方向相邻的相同字符是连通的。
输入描述
第一行输入一个正整数n,代表字符串的长度。
第二行输入一个长度为n的、仅由小写字母组成的字符串。
1<=n<=10^4
输出描述
输出一个整数表示最小权值。
package main
import "fmt"
var move = [][]int{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}
func cal(v []string) int {
n := len(v)
m := len(v[0])
vis := make([][]bool, n)
for i := range vis {
vis[i] = make([]bool, m)
}
var dfs func(x, y int, c byte)
dfs = func(x, y int, c byte) {
if x < 0 || x >= n || y < 0 || y >= m || vis[x][y] || v[x][y] != c {
return
}
vis[x][y] = true
for _, mv := range move {
dfs(x+mv[0], y+mv[1], c)
}
}
ret := 0
for i := 0; i < n; i++ {
for j := 0; j < m; j++ {
if vis[i][j] {
continue
}
ret++
dfs(i, j, v[i][j])
}
}
return ret
}
func main() {
var n int
fmt.Scan(&n)
var s string
fmt.Scan(&s)
ans := n
for i := 1; i <= n; i++ {
if n%i != 0 {
continue
}
v := make([]string, i)
length := n / i
for j := 0; j < i; j++ {
v[j] = s[j*length : (j+1)*length]
}
ans = min(ans, cal(v))
}
fmt.Println(ans)
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
第五题:小美染色
美拿到了一棵树,每个节点有一个权值。初始每个节点都是白色。
小美有若干次操作,每次操作可以选择两个相邻的节点,如果它们都是白色且权值的乘积是完全平方数,小美就可以把这两个节点同时染红。
小美想知道,自己最多可以染红多少个节点?
输入描述
第一行输入一个正整数n,代表节点的数量。第二行输入n个正整数ai,代表每个节点的权值。接下来的n-1行,每行输入两个正整数u,v,代表节点u和节点v有一条边连接。
1 <= n <= 10^5
1 <= ai <= 10^9
1 <= u, v <= n
输出描述
输出一个整数,表示最多可以染红的节点数量。
package main
import (
"fmt"
"math"
)
const MAXN = 100000 + 5
var g [MAXN][]int
var a [MAXN]int64
var dp0 [MAXN]int64
var dp1 [MAXN]int64
func square(x int64) int64 {
return x * x
}
func check(x int64) bool {
t := math.Sqrt(float64(x))
return square(int64(t)) == x || square(int64(t)-1) == x || square(int64(t)+1) == x
}
func dfs(u, p int) {
dp0[u] = 0
dp1[u] = 0
for _, v := range g[u] {
if v == p {
continue
}
dfs(v, u)
dp0[u] += max(dp0[v], dp1[v])
if check(a[u] * a[v]) {
dp1[u] = max(dp1[u], dp0[u]-max(dp0[v], dp1[v])+dp0[v]+2)
}
}
}
func max(a, b int64) int64 {
if a > b {
return a
}
return b
}
func main() {
var n int
fmt.Scan(&n)
for i := 0; i < n; i++ {
fmt.Scan(&a[i])
}
for i := 1; i < n; i++ {
var u, v int
fmt.Scan(&u, &v)
u--
v--
g[u] = append(g[u], v)
g[v] = append(g[v], u)
}
dfs(0, -1)
fmt.Println(max(dp0[0], dp1[0]))
}