首先想到线段树,然后刚开始写忽然想到树状数组求和岂不是更快,而且编程复杂度又小,于是把之前写的删掉,写树状数组,写完模版之后忽然发现这题竟然是区间修改!
于是又删掉重写,忽然发现不会处理又加又乘的,果断看题解……
经过几乎两个小时的调试,终于1A。
需要注意的是,一定要让线段树的每一个区间保存的值时刻为正确的,这样才能在调用时直接返回。比如说这道题的change和query操作的最后一句话:
sum:=f(g[k<<1]+g[k<<1+1])
而不是
sum:=f(t[k<<1].sum+t[k<<1+1].sum)
时刻记住这点就ok了。一开始我还以为我的模版记错了呢……
代码:
1 type node=record
2 l,r,ti,ad,sum:int64;
3 end;
4 var i,n,m,tagtime,tagadd,ch,x,y,c,p:longint;
5 t:array[0..650000] of node;
6 function f(x:int64):int64;
7 begin
8 f:=x mod p;
9 end;
10 function g(k:longint):longint;
11 begin
12 with t[k] do
13 begin
14 g:=f(f(sum*ti)+f(ad*(r-l+1)));
15 end;
16 end;
17 procedure build(x,y,k:longint);
18 var mid:longint;
19 begin
20 with t[k] do
21 begin
22 l:=x;r:=y;ad:=0;ti:=1;
23 if l=r then begin read(sum);sum:=f(sum);exit;end;
24 mid:=(l+r)>>1;
25 build(l,mid,k<<1);
26 build(mid+1,r,k<<1+1);
27 sum:=f(t[k<<1].sum+t[k<<1+1].sum);
28 end;
29 end;
30 procedure pushdown(k:longint);
31 begin
32 with t[k] do
33 begin
34 if ti<>1 then
35 begin
36 sum:=f(sum*ti);
37 t[k<<1].ti:=f(t[k<<1].ti*ti);
38 t[k<<1].ad:=f(t[k<<1].ad*ti);
39 t[k<<1+1].ti:=f(t[k<<1+1].ti*ti);
40 t[k<<1+1].ad:=f(t[k<<1+1].ad*ti);
41 ti:=1;
42 end;
43 if ad<>0 then
44 begin
45 sum:=f(sum+ad*(r-l+1));
46 t[k<<1].ad:=f(t[k<<1].ad+ad);
47 t[k<<1+1].ad:=f(t[k<<1+1].ad+ad);
48 ad:=0;
49 end;
50 end;
51 end;
52 procedure change(x,y,k:longint);
53 var mid:longint;
54 begin
55 with t[k] do
56 begin
57 if (l=x) and (r=y) then
58 begin
59 ti:=(ti*tagtime) mod p;
60 ad:=(ad*tagtime+tagadd) mod p;
61 exit;
62 end;
63 pushdown(k);
64 mid:=(l+r)>>1;
65 if y<=mid then change(x,y,k<<1)
66 else if x>mid then change(x,y,k<<1+1)
67 else
68 begin
69 change(x,mid,k<<1);
70 change(mid+1,y,k<<1+1);
71 end;
72 sum:=f(g(k<<1)+g(k<<1+1));
73 end;
74 end;
75 function query(x,y,k:longint):longint;
76 var mid:longint;
77 begin
78 with t[k] do
79 begin
80 pushdown(k);
81 if (l=x) and (r=y) then exit(f(sum));
82 mid:=(l+r)>>1;
83 if y<=mid then query:=f(query(x,y,k<<1))
84 else if x>mid then query:=f(query(x,y,k<<1+1))
85 else query:=f(f(query(x,mid,k<<1))+f(query(mid+1,y,k<<1+1)));
86 sum:=f(g(k<<1)+g(k<<1+1));
87 end;
88 end;
89 procedure init;
90 begin
91 readln(n,p);
92 build(1,n,1);
93 end;
94 procedure main;
95 begin
96 readln(m);
97 for i:=1 to m do
98 begin
99 read(ch);
100 if ch=1 then
101 begin
102 readln(x,y,tagtime);
103 tagadd:=0;
104 change(x,y,1);
105 end
106 else if ch=2 then
107 begin
108 readln(x,y,tagadd);
109 tagtime:=1;
110 change(x,y,1);
111 end
112 else
113 begin
114 readln(x,y);
115 writeln(query(x,y,1));
116 end;
117 end;
118 end;
119 begin
120 init;
121 main;
122 end.
虽然现在已经12:30了,但我感觉,很开心。做了这道题,值!
bzoj1789 AHOI 维护数列(线段树),布布扣,bubuko.com
时间: 2024-10-19 02:26:21