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了。一开始我还以为我的模版记错了呢……
代码:
View Code
虽然现在已经12:30了,但我感觉,很开心。做了这道题,值!
于是又删掉重写,忽然发现不会处理又加又乘的,果断看题解……
经过几乎两个小时的调试,终于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了,但我感觉,很开心。做了这道题,值!
相关文章推荐
- bzoj 1798 AHOI 2009 Seq 维护序列 [线段树]
- [BZOJ1500][NOI2005]维护数列(无旋Treap)
- Bzoj1798 AHOI2009 维护序列 线段树模版
- 【BZOJ1095】【ZJOI2007】Hide 捉迷藏 线段树维护括号序列 数据结构的压缩。
- 【BZOJ1798】【Ahoi2009】维护序列seq(线段树)
- 【线段树】Bzoj1798 [AHOI2009] 维护序列
- BZOJ 2124 线段树维护hash值
- 【bzoj1018】 堵塞的交通 线段树维护连通性
- BZOJ 1095: [ZJOI2007]Hide 捉迷藏(线段树维护括号序列)
- BZOJ 1798 [Ahoi2009]维护序列seq (线段树)
- 【BZOJ1095】【ZJOI2007】捉迷藏 括号序列+线段树维护
- 【bzoj4636】蒟蒻的数列 离散化+线段树
- BZOJ1798 AHOI2009 维护数列
- bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治
- BZOJ 5039: [Jsoi2014]序列维护 线段树
- 【bzoj1798】[Ahoi2009]Seq 维护序列seq 线段树
- BZOJ_4184_shallot_线段树按时间分治维护线性基
- BZOJ 2124 等差子序列 线段树维护hash值
- 维护数列 洛谷2042 bzoj1500 NOI2005
- BZOJ1500: [NOI2005]维修数列 Splay维护序列