{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE MultiWayIf #-} import Control.Monad import Control.Monad.ST import Control.Monad.State import Control.Monad.Primitive import Control.Applicative import Control.Arrow import Data.List import Data.Array import Data.Array.IO import Data.Array.ST import Data.IORef import Data.STRef import Data.Maybe import Data.Bits import Data.Ord import Data.Ratio import Data.Int import Data.Char import qualified Data.ByteString.Char8 as BS import qualified Data.Set as Set import qualified Data.Vector as V import qualified Data.Vector.Mutable as VM import qualified Data.Vector.Unboxed as VU import qualified Data.Vector.Unboxed.Mutable as VUM import qualified Data.Vector.Generic as VG import qualified Data.Vector.Generic.Mutable as VGM import Data.Tuple import Data.Function import Text.Printf import Debug.Trace import Numeric modifyArray arr i f = readArray arr i >>= \x -> writeArray arr i (f x) listToTuple2 [a,b] = (a,b) listToTuple3 [a,b,c] = (a,b,c) listToTuple4 [a,b,c,d] = (a,b,c,d) listToTuple5 [a,b,c,d,e] = (a,b,c,d,e) readIntBS = fst . fromJust . BS.readInt for = flip map infixr 1 ? (?) :: Bool -> (a,a) -> a (?) b t = (if b then fst else snd) t main :: IO () main = do n <- readLn :: IO Int q <- readLn :: IO Int qs <- replicateM q $ map readIntBS . BS.words <$> BS.getLine :: IO [[Int]] let add (a,b) (c,d) = (a+c,b+d) inf = -1 :: Int f x@(xa,xb) y = if xa == inf then y else x g (a,b) n = (a*n,b*n) seg <- newRangeSegmentTree n (0,0) add (inf,inf) f g :: IO (IOURangeSegmentTree (Int,Int)) let ((tr,_,_),(ltr,_,_),_,_) = seg (xa,xb) <- (`execStateT` (0,0)) $ do forM_ qs $ \[x,l,r] -> do case x of 0 -> (lift $ findRangeSegmentTree seg l (r+1)) >>= \(a,b) -> if | a > b -> modify $ first (+a) | a < b -> modify $ second (+b) | a == b -> return () 1 -> lift $ modifyRangeSegmentTree seg l (r+1) (const (1,0)) 2 -> lift $ modifyRangeSegmentTree seg l (r+1) (const (0,1)) --print =<< show <$> findRangeSegmentTree seg 0 n --print =<< VU.toList <$> VU.freeze tr --print =<< VU.freeze ltr (ya,yb) <- findRangeSegmentTree seg 0 n printf "%d %d\n" (xa+ya) (xb+yb) {-- 範囲更新・範囲取得のセグメント木--} type MRangeSegmentTree v s a = ((v s a, a, (a -> a -> a)), (v s a, a, (a -> a -> a)), Int, (a -> Int -> a)) -- 範囲取得用の(セグメント木,単位元,二項演算)、範囲更新用の(遅延セグメント木,単位元,二項演算) type STRangeSegmentTree s a = MRangeSegmentTree VM.MVector s a type IORangeSegmentTree a = STRangeSegmentTree RealWorld a type STURangeSegmentTree s a = MRangeSegmentTree VUM.MVector s a type IOURangeSegmentTree a = STURangeSegmentTree RealWorld a newRangeSegmentTree :: (Applicative m, PrimMonad m, VGM.MVector v a) => Int -> a -> (a -> a -> a) -> a -> (a -> a -> a) -> (a -> Int -> a) -> m (MRangeSegmentTree v (PrimState m) a) newRangeSegmentTree n e1 f1 e2 f2 h = do tree1 <- VGM.replicate m e1 tree2 <- VGM.replicate m e2 return ((tree1,e1,f1),(tree2,e2,f2), m, h) where m = 2 * (2 ^ (ceiling $ logBase 2 (fromIntegral n))) - 1 modifyRangeSegmentTree :: (Applicative m, Eq a, PrimMonad m, VGM.MVector v a) => MRangeSegmentTree v (PrimState m) a -> Int -> Int -> (a -> a) -> m () modifyRangeSegmentTree ((tree,e1,f1),(lazy,e2,f2),size,h) x y g = do void $ aux 0 0 n where n = size `div` 2 + 1 aux i l r = do propag i (r-l) if | r <= x || y <= l -> VGM.read tree i | x <= l && r <= y -> g <$> VGM.read lazy i >>= (\a -> VGM.write lazy i a >> VGM.read tree i >>= \b -> return ( (h a (r-l)))) | otherwise -> f1 <$> aux (i*2+1) l ((l+r)`div`2) <*> aux (i*2+2) ((l+r)`div`2) r >>= (\a -> VGM.write tree i a >> return a) propag i len = do a <- VGM.read lazy i when (a /= e2) $ do when (i VGM.read lazy (i*2+1) VGM.write lazy (i*2+2) =<< f2 a <$> VGM.read lazy (i*2+2) VGM.write tree i =<< (\a b -> (f2 (h b len) a)) <$> VGM.read tree i <*> VGM.read lazy i VGM.write lazy i e2 findRangeSegmentTree :: (Applicative m, Eq a, PrimMonad m, VGM.MVector v a) => MRangeSegmentTree v (PrimState m) a -> Int -> Int -> m a findRangeSegmentTree ((tree1,e1,f1),(tree2,e2,f2),size,h) x y = do aux 0 0 n where n = size `div` 2 + 1 aux i l r = do propag i (r-l) if | r <= x || y <= l -> return e1 | x <= l && r <= y -> VGM.read tree1 i | otherwise -> f1 <$> aux (i*2+1) l ((l+r)`div`2) <*> aux (i*2+2) ((l+r)`div`2) r propag i len = do a <- VGM.read tree2 i when (a /= e2) $ do when (i VGM.read tree2 (i*2+1) VGM.write tree2 (i*2+2) =<< f2 a <$> VGM.read tree2 (i*2+2) VGM.write tree1 i =<< (\a b -> (f2 (h b len) a)) <$> VGM.read tree1 i <*> VGM.read tree2 i VGM.write tree2 i e2