For problem statement at 2000-2999/2000-2099/2060-2069/2069/problemF.txt this is a correct solution, but verifier at 2000-2999/2000-2099/2060-2069/2069/verifierF.go ends with mismatch on iteration 1
input:
385 42
A 253 49
B 310 28
B 251 231
B 307 324
A 43 113
B 6 301
A 1 242
A 384 8
A 42 6
A 107 182
A 157 342
A 322 5
B 56 109
B 21 321
A 63 171
B 149 237
B 13 12
B 348 296
B 3 54
B 217 208
A 216 36
B 3 369
A 209 168
A 351 110
A 326 174
B 271 153
A 292 277
B 363 166
A 202 98
B 279 9
A 318 44
B 276 43
B 384 162
A 309 292
B 179 172
A 292 94
B 196 174
A 217 146
B 312 41
A 315 159
B 267 250
A 102 251
reference:
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
candidate:
0
1
2
3
3
4
4
4
4
4
4
4
5
6
6
7
8
9
10
11
11
12
12
12
12
13
13
14
14
15
15
16
17
17
18
18
19
19
20
20
21
21
exit status 1 can you fix the verifier? package main
import (
"bufio"
"os"
"strconv"
)
type Edge struct {
u, v int32
}
type DSU struct {
parent []int32
sz []int32
comps int
hist []int32
}
func NewDSU(n int) *DSU {
parent := make([]int32, n+1)
sz := make([]int32, n+1)
for i := 1; i <= n; i++ {
parent[i] = int32(i)
sz[i] = 1
}
return &DSU{
parent: parent,
sz: sz,
comps: n,
hist: make([]int32, 0, 1000000),
}
}
func (d *DSU) Find(i int32) int32 {
for i != d.parent[i] {
i = d.parent[i]
}
return i
}
func (d *DSU) Union(i, j int32) {
rootI := d.Find(i)
rootJ := d.Find(j)
if rootI != rootJ {
if d.sz[rootI] < d.sz[rootJ] {
rootI, rootJ = rootJ, rootI
}
d.parent[rootJ] = rootI
d.sz[rootI] += d.sz[rootJ]
d.comps--
d.hist = append(d.hist, rootJ)
} else {
d.hist = append(d.hist, 0)
}
}
func (d *DSU) Undo() {
last := len(d.hist) - 1
rootJ := d.hist[last]
d.hist = d.hist[:last]
if rootJ != 0 {
rootI := d.parent[rootJ]
d.sz[rootI] -= d.sz[rootJ]
d.parent[rootJ] = rootJ
d.comps++
}
}
var treeA [][]Edge
var treeAB [][]Edge
func addEdge(tree [][]Edge, node, l, r, ql, qr int, e Edge) {
if l > qr || r < ql {
return
}
if ql <= l && r <= qr {
tree[node] = append(tree[node], e)
return
}
mid := l + (r-l)/2
addEdge(tree, 2*node, l, mid, ql, qr, e)
addEdge(tree, 2*node+1, mid+1, r, ql, qr, e)
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024)
scanInt := func() int {
scanner.Scan()
res, _ := strconv.Atoi(scanner.Text())
return res
}
scanString := func() string {
scanner.Scan()
return scanner.Text()
}
n := scanInt()
q := scanInt()
treeA = make([][]Edge, 4*q+1)
treeAB = make([][]Edge, 4*q+1)
inA := make(map[int64]bool)
inB := make(map[int64]bool)
lastA := make(map[int64]int)
lastAB := make(map[int64]int)
countAB := make(map[int64]int)
for i := 1; i <= q; i++ {
t := scanString()
u := scanInt()
v := scanInt()
if u > v {
u, v = v, u
}
key := int64(u)<<32 | int64(v)
edge := Edge{int32(u), int32(v)}
if t == "A" {
if inA[key] {
inA[key] = false
addEdge(treeA, 1, 1, q, lastA[key], i-1, edge)
countAB[key]--
if countAB[key] == 0 {
addEdge(treeAB, 1, 1, q, lastAB[key], i-1, edge)
}
} else {
inA[key] = true
lastA[key] = i
countAB[key]++
if countAB[key] == 1 {
lastAB[key] = i
}
}
} else {
if inB[key] {
inB[key] = false
countAB[key]--
if countAB[key] == 0 {
addEdge(treeAB, 1, 1, q, lastAB[key], i-1, edge)
}
} else {
inB[key] = true
countAB[key]++
if countAB[key] == 1 {
lastAB[key] = i
}
}
}
}
for key, in := range inA {
if in {
u, v := int32(key>>32), int32(key)
addEdge(treeA, 1, 1, q, lastA[key], q, Edge{u, v})
}
}
for key, count := range countAB {
if count > 0 {
u, v := int32(key>>32), int32(key)
addEdge(treeAB, 1, 1, q, lastAB[key], q, Edge{u, v})
}
}
ans := make([]int, q+1)
dsuA := NewDSU(n)
dsuAB := NewDSU(n)
var dfs func(node, l, r int)
dfs = func(node, l, r int) {
for _, e := range treeA[node] {
dsuA.Union(e.u, e.v)
}
for _, e := range treeAB[node] {
dsuAB.Union(e.u, e.v)
}
if l == r {
ans[l] = dsuA.comps - dsuAB.comps
} else {
mid := l + (r-l)/2
dfs(2*node, l, mid)
dfs(2*node+1, mid+1, r)
}
for i := 0; i < len(treeA[node]); i++ {
dsuA.Undo()
}
for i := 0; i < len(treeAB[node]); i++ {
dsuAB.Undo()
}
}
if q > 0 {
dfs(1, 1, q)
}
writer := bufio.NewWriter(os.Stdout)
for i := 1; i <= q; i++ {
writer.WriteString(strconv.Itoa(ans[i]) + "\n")
}
writer.Flush()
}