POJ 3468
POJ 3468
题目之前的吐槽:最近记忆力真的差很多了,刚刚做完来写解题报告,题目编号已然不记得….
题目大意:给出n个数,我们有两个操作,q,x,y:询问区间[x,y]的和,c,x,y,z:区间[x,y]里的每一个数+z。
解:树状数组,线段树,以及discuss里说splay可做。做这题目前用的线段树。线段树的常数真心恶心,递归就算了,而且clear操作写成函数那个常数大得我不敢看了,可是不写成函数又会把自己恶心到。
主要是靠一个lazy操作,有一个tag域,如果这个区间在增加的区间内,tag累加,tag表示这个区间要加的数,然后每进入一条线段,clear,更新sum,tag直0,并且把tag传递给子节点(线段)(因为自线段的sum域没有更新)。本体wa点也是很多,首先每看清题目,数据范围超过maxlongint,然后也没想到增加的数可能为负,然后我写的条件是tag>0 then…,然后在累加数的时候,从子节点返回时,需要clear一次,然后 sum := _sum(sons.sum),累加的时候退出不用clear了,进入的时候clear就行(毕竟不像_addnum,他是改变了值的了),然后自己的函数命名的习惯还是改不太过来…
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //poj 3468
2 const
3 inf='1.txt';
4 maxn=111111;
5 type
6 data=record
7 mid, l, r, st, ed: longint;
8 sum, tag: int64;
9 end;
10 var
11 tree: array[0..maxn*4]of data;
12 a: array[0..maxn]of int64;
13 n, q: longint;
14 ans: int64;
15 procedure _clear(k: longint);
16 begin
17 with tree[k] do if tag <> 0 then begin
18 sum := sum + tag*(ed-st+1);
19 if (st<>ed) then begin
20 tree[l].tag := tree[l].tag + tag;
21 tree[r].tag := tree[r].tag + tag;
22 end;
23 tag := 0;
24 end;
25 end;
26
27 procedure _build(s, e, k: longint);
28 begin
29 with tree[k] do begin
30 st := s; ed := e; mid := (st+ed)>>1;
31 if s=e then begin
32 sum := a[s]; exit;
33 end;
34 l := k << 1; _build(s, mid, l);
35 r := l + 1; _build(mid+1, e, r);
36 sum := tree[l].sum + tree[r].sum;
37 end;
38 end;
39
40 procedure _init;
41 var
42 i: longint;
43 begin
44 fillchar(tree, sizeof(tree), 0);
45 readln(n, q);
46 for i := 1 to n do read(a[i]);
47 readln;
48 _build(1, n, 1);
49 end;
50
51 procedure _count(s, e, k: longint);
52 begin
53 with tree[k] do begin
54 _clear(k);
55 if (s<=st)and(ed<=e) then begin
56 ans := ans + sum; exit;
57 end;
58 if s<=mid then _count(s, e, l);
59 if e>mid then _count(s, e, r);
60 if (l>0) then _clear(l);
61 if (r>0) then _clear(r);
62 end;
63 end;
64
65 procedure _addnum(s, e, k: longint; num: int64);
66 begin
67 with tree[k] do begin
68 _clear(k);
69 if (s<=st)and(ed<=e) then begin
70 tag := tag + num; exit;
71 end;
72 if s<=mid then _addnum(s, e, l, num);
73 if e>mid then _addnum(s, e, r, num);
74 if (l>0) then _clear(l);
75 if (r>0) then _clear(r);
76 sum := tree[l].sum + tree[r].sum;
77 end;
78 end;
79
80 procedure _main;
81 var
82 i, x, y, z: longint;
83 c: char;
84 begin
85 for i := 1 to q do begin
86 read(c);
87 if c='Q' then begin
88 readln(x, y);
89 ans := 0;
90 _count(x, y, 1);
91 writeln(ans);
92 end
93 else begin
94 readln(x, y, z);
95 _addnum(x, y, 1, z);
96 end;
97 end;
98 end;
99
100 begin
101 assign(input,inf); reset(input);
102 _init;
103 _main;
104 end.
新增加一个splay版本
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //orzorzorz 2 const 3 maxn=100011; 4 inf='1.txt'; 5 null=maxn; 6 type 7 node=record 8 tag, key, sum: int64; {sb= =} 9 father, size: longint; 10 son: array[0..1]of longint; 11 end; 12 var 13 tree: array[0..maxn]of node; 14 root, n, q, tot: longint; 15 procedure clear(x: longint); 16 begin 17 if (tree[x].tag<>0)and(x<>null) then 18 with tree[x] do begin 19 key := key + tag; 20 inc(tree[son[0]].tag, tag); 21 inc(tree[son[1]].tag, tag); 22 tree[son[0]].sum := tree[son[0]].sum + tag * tree[son[0]].size; 23 tree[son[1]].sum := tree[son[1]].sum + tag * tree[son[1]].size; 24 tag := 0; 25 end; 26 end; 27 28 procedure updata(x: longint); 29 begin 30 with tree[x] do begin 31 sum := tree[son[0]].sum + key + tree[son[1]].sum; 32 size := tree[son[0]].size + 1 + tree[son[1]].size; 33 end; 34 end; 35 36 function find(x: longint): longint; 37 var 38 i : longint; 39 begin 40 i := root; 41 while true do with tree[i] do begin 42 clear(x); 43 if tree[son[0]].size + 1 = x then exit(i); 44 if tree[son[0]].size + 1 > x then i := son[0] 45 else begin 46 x := x - tree[son[0]].size - 1; 47 i := son[1]; 48 end; 49 end; 50 end; 51 52 procedure rotate(x: longint); 53 var 54 isr, y, z: longint; 55 begin 56 with tree[x] do begin 57 y := father; if y=root then root := x; 58 if tree[y].son[1] = x then isr := 1 else isr := 0; 59 {clear son} //clear(tree[y].son[0]); clear(tree[y].son[1]); clear(son[0]); clear(son[1]); 60 clear(y); clear(x); 61 tree[y].son[isr] := son[isr xor 1]; 62 if son[isr xor 1]<>null then tree[son[isr xor 1]].father := y; 63 z := tree[y].father; father := z; 64 if z<>null then begin 65 if y=tree[z].son[0] then tree[z].son[0] := x 66 else tree[z].son[1] := x; 67 end; 68 tree[y].father := x; 69 tree[x].son[isr xor 1] := y; 70 end; 71 updata(y); 72 end; 73 74 procedure splay(x, goal: longint); 75 var 76 u, v, y, z: longint; 77 begin 78 while tree[x].father<>goal do with tree[x] do begin 79 y := father; if tree[y].father=goal then begin 80 rotate(x); continue; 81 end; 82 z := tree[y].father; 83 if tree[y].son[0]=x then u := 0 else u := 1; 84 if tree[z].son[0]=y then v := 0 else v := 1; 85 if (u xor v=0) then begin 86 rotate(y); rotate(x); 87 end 88 else begin 89 rotate(x); rotate(x); 90 end; 91 end; 92 updata(x); 93 end; 94 95 procedure change(x, y, number: longint); 96 var 97 l, r : longint; 98 begin 99 l := find(x-1); 100 splay(l, null); 101 r := find(y+1); 102 splay(r, root); 103 r := tree[r].son[0]; 104 with tree[r] do begin 105 inc(tag, number); 106 clear(r); 107 end; 108 updata(r); 109 updata(tree[root].son[1]); 110 updata(root); 111 end; 112 113 function query(x, y: longint): int64; 114 var 115 l, r: longint; 116 begin 117 l := find(x-1); 118 splay(l, null); 119 r := find(y+1); 120 splay(r, root); 121 r := tree[r].son[0]; 122 query := tree[r].sum; 123 end; 124 125 126 procedure main; 127 var 128 i, a, b, c: longint; 129 ask: char; 130 begin 131 for i := 1 to q do begin 132 read(ask); 133 if ask='Q' then begin 134 readln(a, b); inc(a); inc(b); 135 writeln(query(a, b)); 136 end 137 else begin 138 readln(a, b, c); inc(a); inc(b); 139 change(a, b, c); 140 end; 141 end; 142 end; 143 144 procedure init; 145 var 146 i: longint; 147 begin 148 readln(n, q); 149 fillchar(tree[null], sizeof(tree[null]), 0); 150 fillchar(tree[0], sizeof(tree[0]), 0); 151 with tree[0] do begin 152 size := 1; son[0] := null; son[1] := null; father := 1; 153 end; 154 fillchar(tree[n+1], sizeof(tree[n+1]), 0); 155 with tree[(n+1)] do begin 156 size := 1; son[0] := null; son[1] := null; father := n; 157 end; 158 for i := 1 to n do with tree[i] do begin 159 son[0] := i-1; son[1] := null; father := i+1; tag := 0; 160 if i=n then son[1] := n+1; 161 read(key); 162 updata(i); 163 end; readln; 164 root := n; 165 tree[root].father := null; 166 end; 167 168 begin 169 assign(input,inf); reset(input); assign(output,'2.txt'); rewrite(output); 170 init; 171 main; 172 end.