@@ -36,8 +36,136 @@ def make_list(n, *args, default=0): return [make_list(*args, default=default) fo
3636
3737sys .setrecursionlimit (1000000 )
3838
39+
40+ # モノイドに対して適用可能、Nが2冪でなくても良い
41+ class LazySegmentTree ():
42+ '''
43+ Affine変換(x <- bx + c)の際の各関数の例
44+
45+ monoid_identity = 0
46+ operator_identity = (1,0)
47+
48+ def monoid_func(x,y):
49+ return (x+y) % MOD
50+ def composition(f,g): #g(f(x))の順に作用する
51+ b0,c0 = f
52+ b1,c1 = g
53+ return ((b0*b1) % MOD,(b1*c0+c1) % MOD)
54+ def effect(x,f,r): #xは格納されているデータ(モノイド)
55+ b,c = f
56+ return (b*x+c*r) % MOD
57+ '''
58+
59+ def __init__ (self , initial_values , monoid_func , composition , effect , monoid_identity , operator_identity ):
60+ self .N = len (initial_values )
61+ self .monoid_func = monoid_func
62+ self .composition = composition # composition(f, g) => g(f(x))の順であることに注意
63+ self .effect = effect #右作用 effect(a, f) => f(a), 雑に可換な処理を書こうとするとバグるので注意
64+ self .monoid_identity = monoid_identity
65+ self .operator_identity = operator_identity
66+ self .data = [self .monoid_identity ]* (2 * self .N )
67+ self .lazy = [self .operator_identity ]* (2 * self .N )
68+ self .size = [0 ]* (2 * self .N )
69+
70+ for i , ai in enumerate (initial_values ):
71+ self .data [self .N + i ] = ai
72+ self .size [self .N + i ] = 1
73+ for i in range (self .N - 1 ,0 ,- 1 ):
74+ self .data [i ] = self .monoid_func (self .data [i << 1 ], self .data [i << 1 | 1 ])
75+ self .size [i ] = self .size [i << 1 ] + self .size [i << 1 | 1 ]
76+
77+ def update (self ,i ,x ): # i番目(0-index)の値をxに変更
78+ i += self .N
79+ self .data [i ] = x
80+ while i > 1 :
81+ i >>= 1
82+ self .data [i ] = self .monoid_func (self .data [i << 1 ], self .data [i << 1 | 1 ])
83+
84+ def eval_at (self ,i ): # i番目で作用を施した値を返す
85+ return self .effect (self .data [i ],self .lazy [i ],self .size [i ])
86+
87+ def eval_above (self ,i ): # i番目より上の値を再計算する
88+ while i > 1 :
89+ i >>= 1
90+ self .data [i ] = self .monoid_func (self .eval_at (i << 1 ),self .eval_at (i << 1 | 1 ))
91+
92+ def propagate_at (self ,i ): # i番目で作用を施し、1つ下に作用の情報を伝える
93+ self .data [i ] = self .effect (self .data [i ],self .lazy [i ],self .size [i ])
94+ self .lazy [i << 1 ] = self .composition (self .lazy [i << 1 ],self .lazy [i ])
95+ self .lazy [i << 1 | 1 ] = self .composition (self .lazy [i << 1 | 1 ], self .lazy [i ])
96+ self .lazy [i ] = self .operator_identity
97+
98+ def propagate_above (self ,i ): # i番目より上で作用を施す
99+ H = i .bit_length ()
100+ for h in range (H ,0 ,- 1 ):
101+ self .propagate_at (i >> h )
102+
103+ def fold (self , L , R ): # [L,R)の区間取得
104+ L += self .N
105+ R += self .N
106+ L0 = L // (L & - L )
107+ R0 = R // (R & - R ) - 1
108+ self .propagate_above (L0 )
109+ self .propagate_above (R0 )
110+ vL = self .monoid_identity
111+ vR = self .monoid_identity
112+ while L < R :
113+ if L & 1 :
114+ vL = self .monoid_func (vL ,self .eval_at (L ))
115+ L += 1
116+ if R & 1 :
117+ R -= 1
118+ vR = self .monoid_func (self .eval_at (R ),vR )
119+ L >>= 1
120+ R >>= 1
121+ return self .monoid_func (vL ,vR )
122+
123+ def apply_range (self ,L ,R ,x ):# 区間 [L,R) にxを作用
124+ L += self .N
125+ R += self .N
126+ L0 = L // (L & - L )
127+ R0 = R // (R & - R ) - 1
128+ self .propagate_above (L0 )
129+ self .propagate_above (R0 )
130+ while L < R :
131+ if L & 1 :
132+ self .lazy [L ] = self .composition (self .lazy [L ], x )
133+ L += 1
134+ if R & 1 :
135+ R -= 1
136+ self .lazy [R ] = self .composition (self .lazy [R ], x )
137+ L >>= 1
138+ R >>= 1
139+ self .eval_above (L0 )
140+ self .eval_above (R0 )
141+
39142def main ():
40- N = I ()
143+ N , Q = LI ()
144+ A = LI ()
145+ X = [(1 - a , a , 0 ) for a in A ]
146+ query = LIR (Q )
147+
148+ monoid_identity = (0 , 0 , 0 )
149+ operator_identity = 0
150+
151+ def monoid_func (x ,y ):
152+ return (x [0 ] + y [0 ], x [1 ] + y [1 ], x [2 ] + y [2 ] + x [1 ] * y [0 ])
153+
154+ def composition (f , g ):
155+ return f ^ g
156+
157+ def effect (x , f , r ):
158+ c0 , c1 , cnt = x
159+ return (c1 , c0 , c0 * c1 - cnt ) if f else x
160+
161+ seg = LazySegmentTree (X , monoid_func , composition , effect , monoid_identity , operator_identity )
162+
163+ for t , l , r in query :
164+ if t == 1 :
165+ seg .apply_range (l - 1 , r , 1 )
166+ else :
167+ print (seg .fold (l - 1 , r )[- 1 ])
168+
41169
42170if __name__ == '__main__' :
43171 main ()
0 commit comments