您的位置:首页 > 运维架构

bzoj1789 AHOI 维护数列(线段树)

2014-06-07 00:33 190 查看
首先想到线段树,然后刚开始写忽然想到树状数组求和岂不是更快,而且编程复杂度又小,于是把之前写的删掉,写树状数组,写完模版之后忽然发现这题竟然是区间修改!

于是又删掉重写,忽然发现不会处理又加又乘的,果断看题解……

经过几乎两个小时的调试,终于1A。

需要注意的是,一定要让线段树的每一个区间保存的值时刻为正确的,这样才能在调用时直接返回。比如说这道题的change和query操作的最后一句话:

sum:=f(g[k<<1]+g[k<<1+1])

而不是

sum:=f(t[k<<1].sum+t[k<<1+1].sum)

时刻记住这点就ok了。一开始我还以为我的模版记错了呢……

代码:

type node=record
l,r,ti,ad,sum:int64;
end;
var i,n,m,tagtime,tagadd,ch,x,y,c,p:longint;
t:array[0..650000] of node;
function f(x:int64):int64;
begin
f:=x mod p;
end;
function g(k:longint):longint;
begin
with t[k] do
begin
g:=f(f(sum*ti)+f(ad*(r-l+1)));
end;
end;
procedure build(x,y,k:longint);
var mid:longint;
begin
with t[k] do
begin
l:=x;r:=y;ad:=0;ti:=1;
if l=r then begin read(sum);sum:=f(sum);exit;end;
mid:=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1+1);
sum:=f(t[k<<1].sum+t[k<<1+1].sum);
end;
end;
procedure pushdown(k:longint);
begin
with t[k] do
begin
if ti<>1 then
begin
sum:=f(sum*ti);
t[k<<1].ti:=f(t[k<<1].ti*ti);
t[k<<1].ad:=f(t[k<<1].ad*ti);
t[k<<1+1].ti:=f(t[k<<1+1].ti*ti);
t[k<<1+1].ad:=f(t[k<<1+1].ad*ti);
ti:=1;
end;
if ad<>0 then
begin
sum:=f(sum+ad*(r-l+1));
t[k<<1].ad:=f(t[k<<1].ad+ad);
t[k<<1+1].ad:=f(t[k<<1+1].ad+ad);
ad:=0;
end;
end;
end;
procedure change(x,y,k:longint);
var mid:longint;
begin
with t[k] do
begin
if (l=x) and (r=y) then
begin
ti:=(ti*tagtime) mod p;
ad:=(ad*tagtime+tagadd) mod p;
exit;
end;
pushdown(k);
mid:=(l+r)>>1;
if y<=mid then change(x,y,k<<1)
else if x>mid then change(x,y,k<<1+1)
else
begin
change(x,mid,k<<1);
change(mid+1,y,k<<1+1);
end;
sum:=f(g(k<<1)+g(k<<1+1));
end;
end;
function query(x,y,k:longint):longint;
var mid:longint;
begin
with t[k] do
begin
pushdown(k);
if (l=x) and (r=y) then exit(f(sum));
mid:=(l+r)>>1;
if y<=mid then query:=f(query(x,y,k<<1))
else if x>mid then query:=f(query(x,y,k<<1+1))
else query:=f(f(query(x,mid,k<<1))+f(query(mid+1,y,k<<1+1)));
sum:=f(g(k<<1)+g(k<<1+1));
end;
end;
procedure init;
begin
readln(n,p);
build(1,n,1);
end;
procedure main;
begin
readln(m);
for i:=1 to m do
begin
read(ch);
if ch=1 then
begin
readln(x,y,tagtime);
tagadd:=0;
change(x,y,1);
end
else if ch=2 then
begin
readln(x,y,tagadd);
tagtime:=1;
change(x,y,1);
end
else
begin
readln(x,y);
writeln(query(x,y,1));
end;
end;
end;
begin
init;
main;
end.


View Code
虽然现在已经12:30了,但我感觉,很开心。做了这道题,值!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: