QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#880750 | #10016. Divine Tree | Qingyu | AC ✓ | 0ms | 2304kb | Rust | 18.8kb | 2025-02-03 19:28:49 | 2025-02-03 19:28:50 |
Judging History
answer
use std::collections::*;
use std::io::Write;
type Map<K, V> = BTreeMap<K, V>;
type Set<T> = BTreeSet<T>;
type Deque<T> = VecDeque<T>;
fn run() {
input! {
n: usize,
s: bytes,
e: [(usize1, usize1, i64); n - 1],
q: usize,
ask: [(usize1, i64); q],
}
let mut s = s;
let mut cnt = [0; 2];
for s in s.iter_mut() {
if *s == b'G' {
*s = 0;
} else {
*s = 1;
}
cnt[*s as usize] += 1;
}
let out = std::io::stdout();
let mut out = std::io::BufWriter::new(out.lock());
if cnt[0].max(cnt[1]) == n {
for _ in 0..q {
writeln!(out, "0").ok();
}
return;
}
let mut g = vec![vec![]; n];
let mut hld = HLD::new(n);
for &(a, b, c) in e.iter() {
g[a].push(b);
g[b].push(a);
hld.add_edge(a, b);
}
let topo = |src: usize| -> Vec<(usize, usize)> {
let mut res = vec![(0, n)];
for i in 0..n {
let (v, p) = res[i];
for &u in g[v].iter() {
if u != p {
res.push((u, v));
}
}
}
res
};
let ord = topo(0);
let mut root = 0;
let mut size = vec![1; n];
for &(v, p) in ord.iter().rev() {
let mut max = 0usize;
for &u in g[v].iter() {
if u != p {
max = max.max(size[u]);
size[v] += size[u];
}
}
max = max.max(n - size[v]);
if 2 * max <= n {
root = v;
break;
}
}
hld.build(root);
let mut dp = s
.iter()
.map(|s| {
let mut cnt = [0; 2];
cnt[*s as usize] += 1;
cnt
})
.collect::<Vec<_>>();
for i in (0..n).rev() {
let v = hld.vertex(i);
let mut val = dp[v];
for &u in hld.child[v].iter() {
val[0] += dp[u][0];
val[1] += dp[u][1];
}
dp[v] = val;
}
if cnt[0] > cnt[1] {
for dp in dp.iter_mut() {
*dp = [dp[1], dp[0]];
}
cnt = [cnt[1], cnt[0]];
}
let mut pos = vec![];
for i in 0..n {
let v = hld.vertex(i);
let (l, r) = hld.sub_tree(v);
if r - l == cnt[0] {
pos.push(i);
}
}
let mut seg = std::cell::RefCell::new(LazySegmentTree::build(
(0..pos.len()).map(|_| 0),
pos.len(),
R,
));
let update = |k: usize, w: i64| {
let (a, b, _) = e[k];
let (p, c) = if hld.parent[a] == b { (b, a) } else { (a, b) };
let (l, r) = hld.sub_tree(c);
let mut x = pos.lower_bound(&l);
let mut y = pos.lower_bound(&r);
let sub = dp[c];
let mut seg = seg.borrow_mut();
if x > 0 && hld.sub_tree(hld.vertex(pos[x - 1])).1 >= r {
seg.update(x - 1, x, w * sub[1] as i64);
x -= 1;
} else {
let need = cnt[0] - sub[0];
seg.update(x, y, w * need as i64);
}
seg.update(0, x, w * sub[0] as i64);
seg.update(y, pos.len(), w * sub[0] as i64);
};
for i in 0..(n - 1) {
let (a, b, w) = e[i];
update(i, w);
// writeln!(out, "{}", seg.borrow_mut().find(0, pos.len())).ok();
}
for (k, w) in ask {
update(k, w);
writeln!(out, "{}", seg.borrow_mut().find(0, pos.len())).ok();
}
}
struct R;
impl TE for R {
type T = i64;
type E = i64;
fn fold(&self, l: &Self::T, r: &Self::T) -> Self::T {
std::cmp::min(*l, *r)
}
fn eval(&self, x: &Self::T, f: &Self::E) -> Self::T {
*x + *f
}
fn merge(&self, g: &Self::E, h: &Self::E) -> Self::E {
*g + *h
}
fn e(&self) -> Self::T {
std::i64::MAX / 2
}
fn id(&self) -> Self::E {
0
}
}
fn main() {
run();
}
// ---------- begin input macro ----------
// reference: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
#[macro_export]
macro_rules! input {
(source = $s:expr, $($r:tt)*) => {
let mut iter = $s.split_whitespace();
input_inner!{iter, $($r)*}
};
($($r:tt)*) => {
let s = {
use std::io::Read;
let mut s = String::new();
std::io::stdin().read_to_string(&mut s).unwrap();
s
};
let mut iter = s.split_whitespace();
input_inner!{iter, $($r)*}
};
}
#[macro_export]
macro_rules! input_inner {
($iter:expr) => {};
($iter:expr, ) => {};
($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
let $var = read_value!($iter, $t);
input_inner!{$iter $($r)*}
};
}
#[macro_export]
macro_rules! read_value {
($iter:expr, ( $($t:tt),* )) => {
( $(read_value!($iter, $t)),* )
};
($iter:expr, [ $t:tt ; $len:expr ]) => {
(0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
};
($iter:expr, chars) => {
read_value!($iter, String).chars().collect::<Vec<char>>()
};
($iter:expr, bytes) => {
read_value!($iter, String).bytes().collect::<Vec<u8>>()
};
($iter:expr, usize1) => {
read_value!($iter, usize) - 1
};
($iter:expr, $t:ty) => {
$iter.next().unwrap().parse::<$t>().expect("Parse error")
};
}
// ---------- end input macro ----------
// ---------- begin Heavy-Light decomposition ----------
pub struct HLD {
size: usize,
edge: Vec<(usize, usize)>,
child: Vec<Vec<usize>>,
path_root: Vec<usize>,
parent: Vec<usize>,
left: Vec<usize>,
right: Vec<usize>,
inverse: Vec<usize>,
}
impl HLD {
pub fn new(size: usize) -> Self {
assert!(size <= 10usize.pow(8));
HLD {
size: size,
edge: Vec::with_capacity(size - 1),
child: Vec::new(),
path_root: Vec::new(),
parent: Vec::new(),
left: Vec::new(),
right: Vec::new(),
inverse: Vec::new(),
}
}
pub fn add_edge(&mut self, a: usize, b: usize) {
assert!(a != b && a < self.size && b < self.size);
self.edge.push((a, b));
}
pub fn build(&mut self, root: usize) {
assert!(self.edge.len() + 1 == self.size);
let size = self.size;
let mut cnt = vec![0; size];
for &(a, b) in self.edge.iter() {
cnt[a] += 1;
cnt[b] += 1;
}
let mut child = cnt
.into_iter()
.map(|c| Vec::with_capacity(c))
.collect::<Vec<_>>();
for &(a, b) in self.edge.iter() {
child[a].push(b);
child[b].push(a);
}
let mut parent = vec![size; size];
let mut q = Vec::with_capacity(size);
q.push(root);
parent[root] = root;
for i in 0..size {
let v = q[i];
for u in child[v].clone() {
assert!(parent[u] == size);
parent[u] = v;
child[u].retain(|e| *e != v);
q.push(u);
}
}
let mut sum = vec![1; size];
for &v in q.iter().rev() {
let child = &mut child[v];
if !child.is_empty() {
let (pos, _) = child.iter().enumerate().max_by_key(|p| sum[*p.1]).unwrap();
child.swap(0, pos);
sum[v] = 1 + child.iter().fold(0, |s, a| s + sum[*a]);
}
}
let mut path_root = (0..size).collect::<Vec<_>>();
let mut left = vec![0; size];
let mut right = vec![0; size];
let mut dfs = vec![(root, false)];
let mut id = 0;
while let Some((v, end)) = dfs.pop() {
if end {
right[v] = id;
continue;
}
left[v] = id;
id += 1;
dfs.push((v, true));
let child = &child[v];
if !child.is_empty() {
for &u in child[1..].iter() {
path_root[u] = u;
dfs.push((u, false));
}
let u = child[0];
path_root[u] = path_root[v];
dfs.push((u, false));
}
}
let mut inverse = vec![size; size];
for (i, l) in left.iter().enumerate() {
inverse[*l] = i;
}
self.child = child;
self.parent = parent;
self.left = left;
self.right = right;
self.path_root = path_root;
self.inverse = inverse;
}
pub fn lca(&self, mut a: usize, mut b: usize) -> usize {
assert!(a < self.size && b < self.size);
let path = &self.path_root;
let parent = &self.parent;
let index = &self.left;
while path[a] != path[b] {
if index[a] > index[b] {
std::mem::swap(&mut a, &mut b);
}
b = parent[path[b]];
}
std::cmp::min((index[a], a), (index[b], b)).1
}
pub fn path(
&self,
src: usize,
dst: usize,
up: &mut Vec<(usize, usize)>,
down: &mut Vec<(usize, usize)>,
) {
assert!(src < self.size && dst < self.size);
up.clear();
down.clear();
let path = &self.path_root;
let parent = &self.parent;
let index = &self.left;
let mut x = src;
let mut y = dst;
while path[x] != path[y] {
if index[x] > index[y] {
let p = path[x];
assert!(p == path[p]);
up.push((index[p], index[x] + 1));
x = parent[p];
} else {
let p = path[y];
assert!(p == path[p]);
down.push((index[p], index[y] + 1));
y = parent[p];
}
}
if index[x] <= index[y] {
down.push((index[x], index[y] + 1));
} else {
up.push((index[y], index[x] + 1));
}
down.reverse();
}
pub fn sub_tree(&self, v: usize) -> (usize, usize) {
assert!(v < self.size);
(self.left[v], self.right[v])
}
pub fn parent(&self, v: usize) -> Option<usize> {
assert!(v < self.size);
let p = self.parent[v];
if p == v {
None
} else {
Some(p)
}
}
// s -> t へのパスの2番目の頂点を返す
pub fn next(&self, s: usize, t: usize) -> usize {
assert!(s < self.size && t < self.size && s != t);
let (a, b) = self.sub_tree(s);
let (c, d) = self.sub_tree(t);
if !(a <= c && d <= b) {
return self.parent[s];
}
let mut pos = t;
let mut pre = t;
while self.path_root[s] != self.path_root[pos] {
pre = self.path_root[pos];
pos = self.parent[pre];
}
if s == pos {
pre
} else {
self.child[s][0]
}
}
pub fn vertex(&self, x: usize) -> usize {
assert!(x < self.size);
self.inverse[x]
}
pub fn jump(
&self,
s: usize,
t: usize,
mut k: usize,
up: &mut Vec<(usize, usize)>,
down: &mut Vec<(usize, usize)>,
) -> Option<usize> {
assert!(s.max(t) < self.size);
self.path(s, t, up, down);
for (l, r) in up.drain(..) {
if k < r - l {
return Some(self.vertex(r - 1 - k));
}
k -= r - l;
}
for (l, r) in down.drain(..) {
if k < r - l {
return Some(self.vertex(l + k));
}
k -= r - l;
}
None
}
}
// ---------- end Heavy-Light decomposition ----------
// ---------- begin Lazy Segment Tree ----------
pub trait TE {
type T: Clone;
type E: Clone;
fn fold(&self, l: &Self::T, r: &Self::T) -> Self::T;
fn eval(&self, x: &Self::T, f: &Self::E) -> Self::T;
fn merge(&self, g: &Self::E, h: &Self::E) -> Self::E;
fn e(&self) -> Self::T;
fn id(&self) -> Self::E;
}
pub struct LazySegmentTree<R: TE> {
n: usize,
size: usize,
bit: u32,
op: R,
data: Vec<(R::T, R::E)>,
}
impl<R: TE> LazySegmentTree<R> {
pub fn new(n: usize, op: R) -> Self {
assert!(n > 0);
let size = n.next_power_of_two();
let bit = size.trailing_zeros();
let data = vec![(op.e(), op.id()); 2 * size];
Self {
n,
size,
bit,
op,
data,
}
}
pub fn build<I>(init: I, n: usize, op: R) -> Self
where
I: Iterator<Item = R::T>,
{
let mut seg = Self::new(n, op);
for (data, ini) in seg.data[seg.size..].iter_mut().zip(init) {
data.0 = ini;
}
for i in (1..seg.size).rev() {
seg.pull(i);
}
seg
}
pub fn update(&mut self, l: usize, r: usize, f: R::E) {
assert!(l <= r && r <= self.n);
if l == r {
return;
}
self.push_range(l, r);
let mut s = l + self.size;
let mut t = r + self.size;
while s < t {
if s & 1 == 1 {
self.apply(s, &f);
s += 1;
}
if t & 1 == 1 {
t -= 1;
self.apply(t, &f);
}
s >>= 1;
t >>= 1;
}
let l = l + self.size;
let r = r + self.size;
for k in 1..=self.bit {
if (l >> k) << k != l {
self.pull(l >> k);
}
if (r >> k) << k != r {
self.pull((r - 1) >> k);
}
}
}
pub fn find(&mut self, l: usize, r: usize) -> R::T {
assert!(l <= r && r <= self.n);
if l == r {
return self.op.e();
}
self.push_range(l, r);
let mut l = l + self.size;
let mut r = r + self.size;
let mut p = self.op.e();
let mut q = self.op.e();
while l < r {
if l & 1 == 1 {
p = self.op.fold(&p, &self.data[l].0);
l += 1;
}
if r & 1 == 1 {
r -= 1;
q = self.op.fold(&self.data[r].0, &q);
}
l >>= 1;
r >>= 1;
}
self.op.fold(&p, &q)
}
pub fn set_at(&mut self, x: usize, v: R::T) {
assert!(x < self.n);
let x = x + self.size;
for k in (1..=self.bit).rev() {
self.push(x >> k);
}
self.data[x].0 = v;
for k in 1..=self.bit {
self.pull(x >> k);
}
}
fn push_range(&mut self, l: usize, r: usize) {
let l = l + self.size;
let r = r + self.size;
for k in (1..=self.bit).rev() {
if (l >> k) << k != l {
self.push(l >> k);
}
if (r >> k) << k != r {
self.push((r - 1) >> k);
}
}
}
fn apply(&mut self, x: usize, f: &R::E) {
self.data[x].0 = self.op.eval(&self.data[x].0, f);
self.data[x].1 = self.op.merge(&self.data[x].1, f);
}
fn push(&mut self, x: usize) {
let f = std::mem::replace(&mut self.data[x].1, self.op.id());
self.apply(2 * x, &f);
self.apply(2 * x + 1, &f);
}
fn pull(&mut self, x: usize) {
self.data[x].0 = self.op.fold(&self.data[2 * x].0, &self.data[2 * x + 1].0);
}
}
// ---------- end Lazy Segment Tree ----------
// ---------- begin super slice ----------
pub trait SuperSlice {
type Item;
fn lower_bound(&self, key: &Self::Item) -> usize
where
Self::Item: Ord;
fn lower_bound_by<F>(&self, f: F) -> usize
where
F: FnMut(&Self::Item) -> std::cmp::Ordering;
fn lower_bound_by_key<K, F>(&self, key: &K, f: F) -> usize
where
K: Ord,
F: FnMut(&Self::Item) -> K;
fn upper_bound(&self, key: &Self::Item) -> usize
where
Self::Item: Ord;
fn upper_bound_by<F>(&self, f: F) -> usize
where
F: FnMut(&Self::Item) -> std::cmp::Ordering;
fn upper_bound_by_key<K, F>(&self, key: &K, f: F) -> usize
where
K: Ord,
F: FnMut(&Self::Item) -> K;
fn next_permutation(&mut self) -> bool
where
Self::Item: Ord;
fn next_permutation_by<F>(&mut self, f: F) -> bool
where
F: FnMut(&Self::Item, &Self::Item) -> std::cmp::Ordering;
fn prev_permutation(&mut self) -> bool
where
Self::Item: Ord;
}
impl<T> SuperSlice for [T] {
type Item = T;
fn lower_bound(&self, key: &Self::Item) -> usize
where
T: Ord,
{
self.lower_bound_by(|p| p.cmp(key))
}
fn lower_bound_by<F>(&self, mut f: F) -> usize
where
F: FnMut(&Self::Item) -> std::cmp::Ordering,
{
self.binary_search_by(|p| f(p).then(std::cmp::Ordering::Greater))
.unwrap_err()
}
fn lower_bound_by_key<K, F>(&self, key: &K, mut f: F) -> usize
where
K: Ord,
F: FnMut(&Self::Item) -> K,
{
self.lower_bound_by(|p| f(p).cmp(key))
}
fn upper_bound(&self, key: &Self::Item) -> usize
where
T: Ord,
{
self.upper_bound_by(|p| p.cmp(key))
}
fn upper_bound_by<F>(&self, mut f: F) -> usize
where
F: FnMut(&Self::Item) -> std::cmp::Ordering,
{
self.binary_search_by(|p| f(p).then(std::cmp::Ordering::Less))
.unwrap_err()
}
fn upper_bound_by_key<K, F>(&self, key: &K, mut f: F) -> usize
where
K: Ord,
F: FnMut(&Self::Item) -> K,
{
self.upper_bound_by(|p| f(p).cmp(key))
}
fn next_permutation(&mut self) -> bool
where
T: Ord,
{
self.next_permutation_by(|a, b| a.cmp(b))
}
fn next_permutation_by<F>(&mut self, mut f: F) -> bool
where
F: FnMut(&Self::Item, &Self::Item) -> std::cmp::Ordering,
{
use std::cmp::Ordering::*;
if let Some(x) = self.windows(2).rposition(|a| f(&a[0], &a[1]) == Less) {
let y = self.iter().rposition(|b| f(&self[x], b) == Less).unwrap();
self.swap(x, y);
self[(x + 1)..].reverse();
true
} else {
self.reverse();
false
}
}
fn prev_permutation(&mut self) -> bool
where
T: Ord,
{
self.next_permutation_by(|a, b| a.cmp(b).reverse())
}
}
// ---------- end super slice ----------
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 2176kb
input:
5 BGGGG 1 3 0 2 1 0 5 2 0 2 4 0 5 2 1 1 3 4 4 3 10 1 2
output:
0 1 1 3 5
result:
ok 5 number(s): "0 1 1 3 5"
Test #2:
score: 0
Accepted
time: 0ms
memory: 2304kb
input:
5 GBBGB 3 2 0 2 1 0 1 4 0 1 5 1000 4 4 1 3 1 2 1 1 1
output:
0 1 3 4
result:
ok 4 number(s): "0 1 3 4"
Test #3:
score: 0
Accepted
time: 0ms
memory: 2304kb
input:
7 GGBBBBG 1 5 101 2 5 101 3 5 100 3 6 100 4 6 100 7 6 100 6 6 1 6 1 6 1 5 3 3 3 6 12345
output:
301 302 303 303 306 711
result:
ok 6 numbers
Test #4:
score: -100
Wrong Answer
time: 0ms
memory: 2176kb
input:
5 BBBBB 1 2 0 1 3 0 2 4 0 2 5 0 5 1 1 2 3 3 3 4 10 2 2
output:
0 0 0 0 0
result:
wrong answer Output contains longer sequence [length = 5], but answer contains 0 elements