-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
WangSenyuan
committed
Jun 24, 2024
1 parent
13ee470
commit c87daf9
Showing
16 changed files
with
1,335 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
Monocarp is playing a computer game (yet again). Guess what is he doing? That's right, killing monsters. | ||
|
||
There are 𝑛 | ||
monsters in a row, numbered from 1 | ||
to 𝑛 | ||
. The 𝑖 | ||
-th monster has two parameters: attack value equal to 𝑎𝑖 | ||
and defense value equal to 𝑑𝑖 | ||
. In order to kill these monsters, Monocarp put a berserk spell on them, so they're attacking each other instead of Monocarp's character. | ||
|
||
The fight consists of 𝑛 | ||
rounds. Every round, the following happens: | ||
|
||
first, every alive monster 𝑖 | ||
deals 𝑎𝑖 | ||
damage to the closest alive monster to the left (if it exists) and the closest alive monster to the right (if it exists); | ||
then, every alive monster 𝑗 | ||
which received more than 𝑑𝑗 | ||
damage during this round dies. I. e. the 𝑗 | ||
-th monster dies if and only if its defense value 𝑑𝑗 | ||
is strictly less than the total damage it received this round. | ||
For each round, calculate the number of monsters that will die during that round. | ||
|
||
|
||
### ideas | ||
1. 能不能反过来计算每个monster能够坚持到第几轮? | ||
2. 这样好像挺麻烦的,就是能够杀死当前monster的是它相邻的两个,但这两个有可能会提前挂掉。情况就变得复杂了 | ||
3. d[i]不会减少 | ||
4. d[i] < a[prev[i]] + a[next[i]] 这样的会被清理掉 | ||
5. 当d[i]被清理掉后,需要知道它新的前继和后继 | ||
6. 且此时需要更新的也就是前继和后继 | ||
7. 应该还是 o(n) * o(lg) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"container/heap" | ||
"fmt" | ||
"os" | ||
) | ||
|
||
func main() { | ||
reader := bufio.NewReader(os.Stdin) | ||
|
||
tc := readNum(reader) | ||
|
||
var buf bytes.Buffer | ||
|
||
for tc > 0 { | ||
tc-- | ||
n := readNum(reader) | ||
a := readNNums(reader, n) | ||
d := readNNums(reader, n) | ||
res := solve(a, d) | ||
s := fmt.Sprintf("%v", res) | ||
buf.WriteString(s[1 : len(s)-1]) | ||
buf.WriteByte('\n') | ||
} | ||
|
||
fmt.Print(buf.String()) | ||
} | ||
|
||
func readString(reader *bufio.Reader) string { | ||
s, _ := reader.ReadString('\n') | ||
for i := 0; i < len(s); i++ { | ||
if s[i] == '\n' || s[i] == '\r' { | ||
return s[:i] | ||
} | ||
} | ||
return s | ||
} | ||
|
||
func readNInt64s(reader *bufio.Reader, n int) []int64 { | ||
res := make([]int64, n) | ||
s, _ := reader.ReadBytes('\n') | ||
|
||
var pos int | ||
|
||
for i := 0; i < n; i++ { | ||
pos = readInt64(s, pos, &res[i]) + 1 | ||
} | ||
|
||
return res | ||
} | ||
|
||
func readInt64(bytes []byte, from int, val *int64) int { | ||
i := from | ||
var sign int64 = 1 | ||
if bytes[i] == '-' { | ||
sign = -1 | ||
i++ | ||
} | ||
var tmp int64 | ||
for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' { | ||
tmp = tmp*10 + int64(bytes[i]-'0') | ||
i++ | ||
} | ||
*val = tmp * sign | ||
return i | ||
} | ||
|
||
func readInt(bytes []byte, from int, val *int) int { | ||
i := from | ||
sign := 1 | ||
if bytes[i] == '-' { | ||
sign = -1 | ||
i++ | ||
} | ||
tmp := 0 | ||
for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' { | ||
tmp = tmp*10 + int(bytes[i]-'0') | ||
i++ | ||
} | ||
*val = tmp * sign | ||
return i | ||
} | ||
|
||
func readNum(reader *bufio.Reader) (a int) { | ||
bs, _ := reader.ReadBytes('\n') | ||
readInt(bs, 0, &a) | ||
return | ||
} | ||
|
||
func readTwoNums(reader *bufio.Reader) (a int, b int) { | ||
res := readNNums(reader, 2) | ||
a, b = res[0], res[1] | ||
return | ||
} | ||
|
||
func readThreeNums(reader *bufio.Reader) (a int, b int, c int) { | ||
res := readNNums(reader, 3) | ||
a, b, c = res[0], res[1], res[2] | ||
return | ||
} | ||
|
||
func readNNums(reader *bufio.Reader, n int) []int { | ||
res := make([]int, n) | ||
x := 0 | ||
bs, _ := reader.ReadBytes('\n') | ||
for i := 0; i < n; i++ { | ||
for x < len(bs) && (bs[x] < '0' || bs[x] > '9') && bs[x] != '-' { | ||
x++ | ||
} | ||
x = readInt(bs, x, &res[i]) | ||
} | ||
return res | ||
} | ||
|
||
func solve(a []int, d []int) []int { | ||
n := len(a) | ||
A := make([]int, n+2) | ||
D := make([]int, n+2) | ||
copy(A[1:], a) | ||
copy(D[1:], d) | ||
D[0] = 1 << 30 | ||
D[n+1] = 1 << 30 | ||
prev := make([]int, n+2) | ||
next := make([]int, n+2) | ||
items := make([]*Item, n+2) | ||
pq := make(PriorityQueue, n+2) | ||
|
||
getValue := func(i int) int { | ||
if i >= 1 && i <= n { | ||
return D[i] - (A[prev[i]] + A[next[i]]) | ||
} | ||
return 1 << 30 | ||
} | ||
|
||
for i := 0; i <= n+1; i++ { | ||
prev[i] = i - 1 | ||
next[i] = i + 1 | ||
it := new(Item) | ||
it.id = i | ||
it.index = i | ||
pq[i] = it | ||
items[i] = it | ||
it.priority = getValue(i) | ||
} | ||
|
||
heap.Init(&pq) | ||
|
||
update := func(it *Item) { | ||
i := it.id | ||
j := prev[i] | ||
k := next[i] | ||
next[j] = k | ||
prev[k] = j | ||
if items[j].index >= 0 { | ||
pq.update(items[j], getValue(j)) | ||
} | ||
if items[k].index >= 0 { | ||
pq.update(items[k], getValue(k)) | ||
} | ||
} | ||
|
||
buf := make([]*Item, n) | ||
|
||
ans := make([]int, n) | ||
var round int | ||
for pq.Len() > 0 && pq[0].priority < 0 { | ||
var p int | ||
for pq.Len() > 0 && pq[0].priority < 0 { | ||
buf[p] = heap.Pop(&pq).(*Item) | ||
p++ | ||
} | ||
ans[round] = p | ||
round++ | ||
for i := 0; i < p; i++ { | ||
update(buf[i]) | ||
} | ||
} | ||
|
||
return ans | ||
} | ||
|
||
// An Item is something we manage in a priority queue. | ||
type Item struct { | ||
id int // The value of the item; arbitrary. | ||
priority int // The priority of the item in the queue. | ||
// The index is needed by update and is maintained by the heap.Interface methods. | ||
index int // The index of the item in the heap. | ||
} | ||
|
||
// A PriorityQueue implements heap.Interface and holds Items. | ||
type PriorityQueue []*Item | ||
|
||
func (pq PriorityQueue) Len() int { return len(pq) } | ||
|
||
func (pq PriorityQueue) Less(i, j int) bool { | ||
return pq[i].priority < pq[j].priority | ||
} | ||
|
||
func (pq PriorityQueue) Swap(i, j int) { | ||
pq[i], pq[j] = pq[j], pq[i] | ||
pq[i].index = i | ||
pq[j].index = j | ||
} | ||
|
||
func (pq *PriorityQueue) Push(x any) { | ||
n := len(*pq) | ||
item := x.(*Item) | ||
item.index = n | ||
*pq = append(*pq, item) | ||
} | ||
|
||
func (pq *PriorityQueue) Pop() any { | ||
old := *pq | ||
n := len(old) | ||
item := old[n-1] | ||
old[n-1] = nil // avoid memory leak | ||
item.index = -1 // for safety | ||
*pq = old[0 : n-1] | ||
return item | ||
} | ||
|
||
// update modifies the priority and value of an Item in the queue. | ||
func (pq *PriorityQueue) update(item *Item, priority int) { | ||
// item.value = value | ||
item.priority = priority | ||
heap.Fix(pq, item.index) | ||
} |
35 changes: 35 additions & 0 deletions
35
src/codeforces/set1/set19/set192/set1922/d/solution_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package main | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func runSample(t *testing.T, a []int, d []int, expect []int) { | ||
res := solve(a, d) | ||
|
||
if !reflect.DeepEqual(res, expect) { | ||
t.Fatalf("Sample expect %v, but got %v", expect, res) | ||
} | ||
} | ||
|
||
func TestSample1(t *testing.T) { | ||
a := []int{3, 4, 7, 5, 10} | ||
d := []int{4, 9, 1, 18, 1} | ||
expect := []int{3, 1, 0, 0, 0} | ||
runSample(t, a, d, expect) | ||
} | ||
|
||
func TestSample2(t *testing.T) { | ||
a := []int{2, 1} | ||
d := []int{1, 3} | ||
expect := []int{0, 0} | ||
runSample(t, a, d, expect) | ||
} | ||
|
||
func TestSample3(t *testing.T) { | ||
a := []int{1, 1, 2, 4} | ||
d := []int{3, 3, 4, 2} | ||
expect := []int{1, 1, 1, 0} | ||
runSample(t, a, d, expect) | ||
} |
Oops, something went wrong.