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,他是改变了值的了),然后自己的函数命名的习惯还是改不太过来…

线段树
  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版本

View Code
  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.

 



posted @ 2012-04-06 20:13  F.D.His.D  阅读(316)  评论(0编辑  收藏  举报