-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathminimum multiple.hs
More file actions
100 lines (80 loc) · 4.1 KB
/
minimum multiple.hs
File metadata and controls
100 lines (80 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
main :: IO()
main = do
n <- fmap read getLine
--nums <- fmap (map read. words) getLine
nums <- fmap (map read. words) getLine
_ <- getLine
contents <- fmap lines getContents
--step contents nums
let queries = map (\x -> (\[[p],q,r] -> (p, read q :: Int, read r :: Int))
(words x)) contents
mapM_ print $ solve n nums queries
--query :: Num a => a -> a -> [a] -> a
query start finish nums = find_lcm $ take (finish - start + 1) (drop start nums)
where
find_lcm xs = (foldl lcm 1 xs) `mod` (10^9+7)
--update :: Num a => a -> a -> [a] -> [a]
update a b nums = take a nums ++ [(nums !! a)*b] ++ drop (a+1) nums
step :: [String] -> [Integer] -> IO()
step [] _ = return ()
step contents nums
| head (head contents) == 'Q' = do
print $ (\[_,a,b] -> query (read a) (read b) nums) $ words (head contents)
step (tail contents) nums
| head (head contents) == 'U' = step (tail contents)
$ (\[_,a,b] -> update (read a) (read b) nums) $ words (head contents)
| otherwise = return ()
--segment tree idea from: http://m00nlight.github.io/functional%20programming/2015/04/11/hackerrank-minimum-multiple
--https://en.wikipedia.org/wiki/Segment_tree
data SegTree = Node {
val :: Integer
, left, right :: Int
, leftChild, rightChild :: SegTree
} |
Leaf {
val :: Integer
, left, right :: Int
}
initSegTree :: Int -> SegTree
initSegTree n = aux 0 (n-1)
where aux l r
| l == r = Leaf {val= -1, left=l, right=r}
| otherwise = let mid = (l + r) `div` 2
in Node { val= -1, left=l, right=r
, leftChild = aux l mid
, rightChild = aux (succ mid) r
}
s_query :: (Int, Int) -> SegTree -> Integer
s_query range@(l,r) root
| r < left root = 1
| l > right root = 1
| l <= left root && right root <= r = val root
| otherwise = lcm (s_query range (leftChild root))
(s_query range (rightChild root))
s_update :: Int -> Integer -> SegTree -> SegTree
s_update i newVal root
| left root <= i && i <= right root = case root of
Leaf {} -> root { val = newVal}
_ -> root { val = lcm newVal (val root)
, leftChild = lChild
, rightChild = rChild
}
| otherwise = root
where
lChild = s_update i newVal $ leftChild root
rChild = s_update i newVal $ rightChild root
p_queries :: [(Char, Int, Int)] -> SegTree -> [Integer] -> [Integer]
p_queries [] _ acc = reverse acc
p_queries (('Q', l, r):q) root acc = let ans = (s_query (l,r) root) `mod` (10^9+7)
in p_queries q root (ans:acc)
p_queries ((_, i, value):q) root acc = let
oldVal = s_query (i,i) root
newVal = oldVal * (fromIntegral value)
nroot = s_update i newVal root
in p_queries q nroot acc
solve :: Int -> [Integer] -> [(Char, Int, Int)] -> [Integer]
solve n arr queries = p_queries queries tree []
where
tree = foldl (\root (i,v) -> s_update i v root)
(initSegTree n)
(zip [0..] arr)