Skip to content

Commit 63f6d91

Browse files
committed
Add examples for ABC157-E
1 parent 2445d01 commit 63f6d91

File tree

5 files changed

+516
-0
lines changed

5 files changed

+516
-0
lines changed

examples/abc157-e-naive.rs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// https://atcoder.jp/contests/abc157/tasks/abc157_e
2+
//
3+
// 以下のクレートを使用。
4+
//
5+
// - `alga`
6+
7+
use alga::general::{AbstractGroup, AbstractMonoid, Additive, Operator};
8+
9+
use std::io::{self, BufWriter, Read as _, StdoutLock, Write as _};
10+
use std::marker::PhantomData;
11+
use std::ops::{RangeInclusive, RangeTo, RangeToInclusive};
12+
13+
fn main() {
14+
let mut input = "".to_owned();
15+
io::stdin().read_to_string(&mut input).unwrap();
16+
let mut input = input.split_whitespace();
17+
macro_rules! read(
18+
//([$tt:tt]) => (read!([$tt; read!(usize)]));
19+
//([$tt:tt; $n:expr]) => ((0..$n).map(|_| read!($tt)).collect::<Vec<_>>());
20+
(($($tt:tt),+)) => (($(read!($tt)),*));
21+
($ty:ty) => (input.next().unwrap().parse::<$ty>().unwrap());
22+
({ Bytes }) => (read!(String).into_bytes());
23+
({ Byte }) => (read!(char) as u8);
24+
({ Usize1 }) => (read!(usize) - 1);
25+
);
26+
27+
let (n, mut s) = read!((usize, { Bytes }));
28+
29+
let mut bits = vec![Bit::<_, Additive>::new(n); 27];
30+
31+
macro_rules! bit(($c:expr) => (bits[usize::from($c - b'a')]));
32+
33+
for (i, c) in s.iter().enumerate() {
34+
bit!(c).plus(i, &1);
35+
}
36+
37+
buf_print(|stdout| {
38+
macro_rules! println(($($tt:tt)*) => (writeln!(stdout, $($tt)*).unwrap()));
39+
for _ in 0..read!(_) {
40+
match read!(_) {
41+
1 => {
42+
let (i, c) = read!(({ Usize1 }, { Byte }));
43+
bit!(s[i]).plus(i, &-1);
44+
bit!(c).plus(i, &1);
45+
s[i] = c;
46+
}
47+
2 => {
48+
let (l, r) = read!(({ Usize1 }, { Usize1 }));
49+
let ans = bits.iter().filter(|bits| bits.query(l..=r) > 0).count();
50+
println!("{}", ans);
51+
}
52+
_ => unreachable!(),
53+
}
54+
}
55+
});
56+
}
57+
58+
// BIT (Binary Indexed Tree)を`alga::general`で抽象化する。
59+
//
60+
// https://docs.rs/alga/0.9/alga/general/index.html
61+
62+
#[derive(Clone, Debug)]
63+
struct Bit<M, O> {
64+
nodes: Vec<M>,
65+
phantom: PhantomData<fn() -> O>,
66+
}
67+
68+
impl<M: AbstractMonoid<O>, O: Operator> Bit<M, O> {
69+
fn new(n: usize) -> Self {
70+
Self {
71+
nodes: vec![M::identity(); n],
72+
phantom: PhantomData,
73+
}
74+
}
75+
76+
fn query<R: BitIndex<M, O>>(&self, range: R) -> M {
77+
range.query(&self.nodes)
78+
}
79+
80+
fn plus(&mut self, i: usize, x: &M) {
81+
let mut i_1based = i + 1;
82+
while i_1based <= self.nodes.len() {
83+
self.nodes[i_1based - 1] = self.nodes[i_1based - 1].operate(x);
84+
i_1based += 1 << i_1based.trailing_zeros();
85+
}
86+
}
87+
}
88+
89+
trait BitIndex<M: AbstractMonoid<O>, O: Operator> {
90+
fn query(&self, nodes: &[M]) -> M;
91+
}
92+
93+
impl<M: AbstractMonoid<O>, O: Operator> BitIndex<M, O> for RangeTo<usize> {
94+
fn query(&self, nodes: &[M]) -> M {
95+
#[allow(clippy::range_minus_one)]
96+
match self.end {
97+
0 => M::identity(),
98+
end => (..=end - 1).query(nodes),
99+
}
100+
}
101+
}
102+
103+
impl<M: AbstractMonoid<O>, O: Operator> BitIndex<M, O> for RangeToInclusive<usize> {
104+
fn query(&self, nodes: &[M]) -> M {
105+
let mut acc = M::identity();
106+
let mut i_1based = self.end + 1;
107+
while i_1based > 0 {
108+
acc = acc.operate(&nodes[i_1based - 1]);
109+
i_1based -= 1 << i_1based.trailing_zeros();
110+
}
111+
acc
112+
}
113+
}
114+
115+
impl<M: AbstractGroup<O>, O: Operator> BitIndex<M, O> for RangeInclusive<usize> {
116+
fn query(&self, nodes: &[M]) -> M {
117+
let l = (..*self.start()).query(nodes);
118+
let r = (..=*self.end()).query(nodes);
119+
r.operate(&l.two_sided_inverse())
120+
}
121+
}
122+
123+
fn buf_print<F: FnMut(&mut BufWriter<StdoutLock<'_>>)>(mut f: F) {
124+
let stdout = io::stdout();
125+
let mut stdout = BufWriter::new(stdout.lock());
126+
f(&mut stdout);
127+
stdout.flush().unwrap();
128+
}

examples/abc157-e-proconio.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// https://atcoder.jp/contests/abc157/tasks/abc157_e
2+
//
3+
// 以下のクレートを使用。
4+
//
5+
// - `alga`
6+
// - `proconio`
7+
8+
use alga::general::{AbstractGroup, AbstractMonoid, Additive, Operator};
9+
use proconio::marker::{Bytes, Usize1};
10+
use proconio::{fastout, input};
11+
12+
use std::marker::PhantomData;
13+
use std::ops::{RangeInclusive, RangeTo, RangeToInclusive};
14+
15+
// `#[proconio::fastout]`で標準出力を高速化する。
16+
//
17+
// https://docs.rs/proconio-derive/0.1.6/proconio_derive/attr.fastout.html
18+
#[fastout]
19+
fn main() {
20+
// `proconio::input!`。
21+
//
22+
// https://docs.rs/proconio/0.3.6/proconio/macro.input.html
23+
input! {
24+
n: usize,
25+
mut s: Bytes,
26+
q: usize,
27+
}
28+
29+
let mut bits = vec![Bit::<_, Additive>::new(n); 27];
30+
31+
macro_rules! bit(($c:expr) => (bits[usize::from($c - b'a')]));
32+
33+
for (i, c) in s.iter().enumerate() {
34+
bit!(c).plus(i, &1);
35+
}
36+
37+
for _ in 0..q {
38+
// `proconio::input!`はオリジナルの`input!`とは違い入力を`lazy_static`で保存しているため、2回以上呼ぶことができる。
39+
40+
input!(kind: u32);
41+
match kind {
42+
1 => {
43+
input!(i: Usize1, c: char);
44+
let c = c as u8;
45+
bit!(s[i]).plus(i, &-1);
46+
bit!(c).plus(i, &1);
47+
s[i] = c;
48+
}
49+
2 => {
50+
input!(l: Usize1, r: Usize1);
51+
let ans = bits.iter().filter(|bits| bits.query(l..=r) > 0).count();
52+
println!("{}", ans);
53+
}
54+
_ => unreachable!(),
55+
}
56+
}
57+
}
58+
59+
// BIT (Binary Indexed Tree)を`alga::general`で抽象化する。
60+
//
61+
// https://docs.rs/alga/0.9/alga/general/index.html
62+
63+
#[derive(Clone, Debug)]
64+
struct Bit<M, O> {
65+
nodes: Vec<M>,
66+
phantom: PhantomData<fn() -> O>,
67+
}
68+
69+
impl<M: AbstractMonoid<O>, O: Operator> Bit<M, O> {
70+
fn new(n: usize) -> Self {
71+
Self {
72+
nodes: vec![M::identity(); n],
73+
phantom: PhantomData,
74+
}
75+
}
76+
77+
fn query<R: BitIndex<M, O>>(&self, range: R) -> M {
78+
range.query(&self.nodes)
79+
}
80+
81+
fn plus(&mut self, i: usize, x: &M) {
82+
let mut i_1based = i + 1;
83+
while i_1based <= self.nodes.len() {
84+
self.nodes[i_1based - 1] = self.nodes[i_1based - 1].operate(x);
85+
i_1based += 1 << i_1based.trailing_zeros();
86+
}
87+
}
88+
}
89+
90+
trait BitIndex<M: AbstractMonoid<O>, O: Operator> {
91+
fn query(&self, nodes: &[M]) -> M;
92+
}
93+
94+
impl<M: AbstractMonoid<O>, O: Operator> BitIndex<M, O> for RangeTo<usize> {
95+
fn query(&self, nodes: &[M]) -> M {
96+
#[allow(clippy::range_minus_one)]
97+
match self.end {
98+
0 => M::identity(),
99+
end => (..=end - 1).query(nodes),
100+
}
101+
}
102+
}
103+
104+
impl<M: AbstractMonoid<O>, O: Operator> BitIndex<M, O> for RangeToInclusive<usize> {
105+
fn query(&self, nodes: &[M]) -> M {
106+
let mut acc = M::identity();
107+
let mut i_1based = self.end + 1;
108+
while i_1based > 0 {
109+
acc = acc.operate(&nodes[i_1based - 1]);
110+
i_1based -= 1 << i_1based.trailing_zeros();
111+
}
112+
acc
113+
}
114+
}
115+
116+
impl<M: AbstractGroup<O>, O: Operator> BitIndex<M, O> for RangeInclusive<usize> {
117+
fn query(&self, nodes: &[M]) -> M {
118+
let l = (..*self.start()).query(nodes);
119+
let r = (..=*self.end()).query(nodes);
120+
r.operate(&l.two_sided_inverse())
121+
}
122+
}

examples/abc157-e-text-io.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// https://atcoder.jp/contests/abc157/tasks/abc157_e
2+
//
3+
// 以下のクレートを使用。
4+
//
5+
// - `alga`
6+
// - `proconio`
7+
// - `text_io`
8+
9+
#[macro_use]
10+
extern crate text_io;
11+
12+
use alga::general::{AbstractGroup, AbstractMonoid, Additive, Operator};
13+
use proconio::fastout;
14+
15+
use std::marker::PhantomData;
16+
use std::ops::{RangeInclusive, RangeTo, RangeToInclusive};
17+
18+
// `#[proconio::fastout]`で標準出力を高速化する。
19+
//
20+
// https://docs.rs/proconio-derive/0.1.6/proconio_derive/attr.fastout.html
21+
#[fastout]
22+
fn main() {
23+
// `text_io::read!()`で値を一つずつ読む。
24+
//
25+
// https://docs.rs/text_io/0.1.8/text_io/macro.read.html
26+
let n: usize = read!();
27+
let mut s = String::into_bytes(read!());
28+
29+
let mut bits = vec![Bit::<_, Additive>::new(n); 27];
30+
31+
macro_rules! bit(($c:expr) => (bits[usize::from($c - b'a')]));
32+
33+
for (i, c) in s.iter().enumerate() {
34+
bit!(c).plus(i, &1);
35+
}
36+
37+
for _ in 0..read!() {
38+
match read!() {
39+
1 => {
40+
let (i, c): (usize, char) = (read!(), read!());
41+
let (i, c) = (i - 1, c as u8);
42+
bit!(s[i]).plus(i, &-1);
43+
bit!(c).plus(i, &1);
44+
s[i] = c;
45+
}
46+
2 => {
47+
let (l, r): (usize, usize) = (read!(), read!());
48+
let (l, r) = (l - 1, r - 1);
49+
let ans = bits.iter().filter(|bits| bits.query(l..=r) > 0).count();
50+
println!("{}", ans);
51+
}
52+
_ => unreachable!(),
53+
}
54+
}
55+
}
56+
57+
// BIT (Binary Indexed Tree)を`alga::general`で抽象化する。
58+
//
59+
// https://docs.rs/alga/0.9/alga/general/index.html
60+
61+
#[derive(Clone, Debug)]
62+
struct Bit<M, O> {
63+
nodes: Vec<M>,
64+
phantom: PhantomData<fn() -> O>,
65+
}
66+
67+
impl<M: AbstractMonoid<O>, O: Operator> Bit<M, O> {
68+
fn new(n: usize) -> Self {
69+
Self {
70+
nodes: vec![M::identity(); n],
71+
phantom: PhantomData,
72+
}
73+
}
74+
75+
fn query<R: BitIndex<M, O>>(&self, range: R) -> M {
76+
range.query(&self.nodes)
77+
}
78+
79+
fn plus(&mut self, i: usize, x: &M) {
80+
let mut i_1based = i + 1;
81+
while i_1based <= self.nodes.len() {
82+
self.nodes[i_1based - 1] = self.nodes[i_1based - 1].operate(x);
83+
i_1based += 1 << i_1based.trailing_zeros();
84+
}
85+
}
86+
}
87+
88+
trait BitIndex<M: AbstractMonoid<O>, O: Operator> {
89+
fn query(&self, nodes: &[M]) -> M;
90+
}
91+
92+
impl<M: AbstractMonoid<O>, O: Operator> BitIndex<M, O> for RangeTo<usize> {
93+
fn query(&self, nodes: &[M]) -> M {
94+
#[allow(clippy::range_minus_one)]
95+
match self.end {
96+
0 => M::identity(),
97+
end => (..=end - 1).query(nodes),
98+
}
99+
}
100+
}
101+
102+
impl<M: AbstractMonoid<O>, O: Operator> BitIndex<M, O> for RangeToInclusive<usize> {
103+
fn query(&self, nodes: &[M]) -> M {
104+
let mut acc = M::identity();
105+
let mut i_1based = self.end + 1;
106+
while i_1based > 0 {
107+
acc = acc.operate(&nodes[i_1based - 1]);
108+
i_1based -= 1 << i_1based.trailing_zeros();
109+
}
110+
acc
111+
}
112+
}
113+
114+
impl<M: AbstractGroup<O>, O: Operator> BitIndex<M, O> for RangeInclusive<usize> {
115+
fn query(&self, nodes: &[M]) -> M {
116+
let l = (..*self.start()).query(nodes);
117+
let r = (..=*self.end()).query(nodes);
118+
r.operate(&l.two_sided_inverse())
119+
}
120+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy