首先想到線段樹,然後剛開始寫忽然想到樹狀陣列求和豈不是更快,而且程式設計複雜度又小,於是把之前寫的刪掉,寫樹狀陣列,寫完模版之後忽然發現這題竟然是區間修改!
於是又刪掉重寫,忽然發現不會處理又加又乘的,果斷看題解……
經過幾乎兩個小時的除錯,終於1a。
需要注意的是,一定要讓線段樹的每乙個區間儲存的值時刻為正確的,這樣才能在呼叫時直接返回。比如說這道題的change和query操作的最後一句話:
sum:=f(g[k<<1]+g[k<<1+1])
而不是sum:=f(t[k<<1].sum+t[k<<1+1].sum)
時刻記住這點就ok了。一開始我還以為我的模版記錯了呢……
**:
1view codetype node=record
2l,r,ti,ad,sum:int64;
3end;4
vari,n,m,tagtime,tagadd,ch,x,y,c,p:longint;
5 t:array[0..650000] of
node;
6function
f(x:int64):int64;
7begin
8 f:=x modp;9
end;
10function
g(k:longint):longint;
11begin
12with t[k] do
13begin
14 g:=f(f(sum*ti)+f(ad*(r-l+1
)));
15end;16
end;
17procedure
build(x,y,k:longint);
18var
mid:longint;
19begin
20with t[k] do
21begin
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);
28end;29
end;
30procedure
pushdown(k:longint);
31begin
32with t[k] do
33begin
34if ti<>1
then
35begin
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;
43if ad<>0
then
44begin
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;
50end;51
end;
52procedure
change(x,y,k:longint);
53var
mid:longint;
54begin
55with t[k] do
56begin
57if (l=x) and (r=y) then
58begin
59 ti:=(ti*tagtime) mod
p;60 ad:=(ad*tagtime+tagadd) mod
p;61
exit;
62end;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
68begin
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;
74end;75
function
query(x,y,k:longint):longint;
76var
mid:longint;
77begin
78with t[k] do
79begin
80pushdown(k);
81if (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;
88end;89
procedure
init;
90begin
91readln(n,p);
92 build(1,n,1
);93
end;
94procedure
main;
95begin
96readln(m);
97for i:=1
to m do
98begin
99read(ch);
100if ch=1
then
101begin
102readln(x,y,tagtime);
103 tagadd:=0
;104 change(x,y,1
);105
end106
else
if ch=2
then
107begin
108readln(x,y,tagadd);
109 tagtime:=1
;110 change(x,y,1
);111
end112
else
113begin
114readln(x,y);
115 writeln(query(x,y,1
));116
end;
117end
;118
end;
119begin
120init;
121main;
122end.
雖然現在已經12:30了,但我感覺,很開心。做了這道題,值!
線段樹 AHOI 2009 維護序列
老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。有長為n的數列,不妨設為a1,a2,an 有如下三種操作形式 1 把數列中的一段數全部乘乙個值 2 把數列中的一段數全部加乙個值 3 詢問數列中的一段數的和,由於答案可能很大,你只需輸出這個數模p的值。第一行兩個整數n和p 1 p 100...
AHOI2009 維護序列 線段樹
老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。有長為n的數列,不妨設為a1,a2,an 有如下三種操作形式 1 把數列中的一段數全部乘乙個值 2 把數列中的一段數全部加乙個值 3 詢問數列中的一段數的和,由於答案可能很大,你只需輸出這個數模p的值。線段樹,打個乘法lazy標記即可 i...
bzoj1798 ahoi2009 維護序列
time limit 30 sec memory limit 64 mb submit 3714 solved 1364 submit status discuss 老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。有長為n的數列,不妨設為a1,a2,an 有如下三種操作形式 1 把數列...