import Control.Monad import qualified Data.ByteString.Char8 as BS import Data.Char import Data.List import Control.Monad.ST import Data.Array.ST import Data.Bool import Data.Maybe main :: IO () main = do [n, q] <- bsGetLnInts as <- bsGetLnInts qs <- replicateM q bsGetLnInts let ans = yuki876 n q as qs mapM_ print ans bsGetLnInts :: IO [Int] bsGetLnInts = unfoldr (BS.readInt . BS.dropWhile isSpace) <$> BS.getLine yuki876 :: Int -> Int -> [Int] -> [[Int]] -> [Int] yuki876 n _q as qs = runST $ do d <- newListArray (0, n1) $ zipWith (-) as (0 : as) :: ST s (STUArray s Int Int) st <- makeSegTree (+) 0 $ zipWith diff1 (0 : as) as :: ST s (SegTree (STUArray s) Int) catMaybes <$> forM qs (action d st) where n1 = pred n diff1 x y = bool 0 1 $ x /= y action d st (1:l:r:x:_) = do let l1 = pred l dl1 <- (x +) <$> readArray d l1 writeArray d l1 dl1 setSegTree st l1 $ diff1 0 dl1 when (r < n) $ do dr1 <- subtract x <$> readArray d r writeArray d r dr1 setSegTree st r $ diff1 0 dr1 return Nothing action d st (2:l:r:_) = Just . succ <$> querySegTree st l r {- a[1~n] 元データ d[0~n-1] 一つ**次**との差分 d[i] = a[i+1] - a[i] ただし a[0] = 0 とする st[0~n-1] 次と異なるとき1、の区間和セグメント木 st[i] = d[i] ? 1 : 0 クエリ1 a[l] が x 増えるので、d[l-1] が x 増える a[r] が x 増えるので、d[r] が x 減る r = N についてやる必要なし -} data SegTree ar a = SegTree (a->a->a) a Int (ar Int a) -- makeSegTree の実行に付ける型注釈 Uなしも可 -- ST s (SegTree (STUArray s) ) -- ST s (SegTree (STUArray s) ) makeSegTree :: MArray ar a m => (a->a->a) -> a -> [a] -> m (SegTree ar a) makeSegTree op e xs = do let len = length xs let w = until (len <=) (2 *) 1 arr <- newArray (0, 2 * pred w) e zipWithM_ (writeArray arr) [pred w ..] xs forM_ [w-2, w-3 .. 0] (\k -> do let kk1 = k + succ k l <- readArray arr kk1 r <- readArray arr (succ kk1) writeArray arr k (op l r) ) return $ SegTree op e w arr setSegTree :: MArray ar a m => SegTree ar a -> Int -> a -> m () setSegTree (SegTree op _ w arr) j x = updateLoop op arr (j + pred w) x -- 内部関数 updateLoop _p arr 0 x = writeArray arr 0 x updateLoop op arr i x = do writeArray arr i x y <- if even i then flip op x <$> readArray arr (pred i) else op x <$> readArray arr (succ i) updateLoop op arr (div (pred i) 2) y querySegTree :: MArray ar a m => SegTree ar a -> Int -> Int -> m a querySegTree (SegTree op e w0 arr) a b = recur 0 w0 0 where recur p w i -- p : i のカバーする範囲の下端添え字 / w : iがカバーする横幅 / i : 注目している物理配列の添え字 | q <= a || b <= p = return e | a <= p && q <= b = readArray arr i | otherwise = do l <- recur p w2 j r <- recur (p + w2) w2 $ succ j return (op l r) where q = p + w w2 = div w 2 j = i + succ i