[POJ3468 A Simple Problem with Integers]

[题目来源]:POJ Monthly--2007.11.25, Yang Yi

[关键字]:线段树

[题目大意]:对于给定区间进行整体添加数值,或询问操作,对于每个询问操作输出该区间数字之和。

//=====================================================================================================

[分析]:对于线段树的操作,没有技巧只是要注意延迟操作和int64。原先写的时候思路并不清楚也没有真正弄明白,下面给出一个比较优美的版本。

[代码]:

View Code
  1 type
2 rec = record
3 x, y, lc, rc: longint;
4 dat, last: int64;
5 end;
6 var
7 n, q, tot: longint;
8 ans: int64;
9 tree: array[0..500100] of rec;
10 a: array[0..100100] of longint;
11
12 procedure build(l, r: longint);
13 var
14 now: longint;
15 begin
16 inc(tot);
17 now := tot;
18 tree[now].x := l;
19 tree[now].y := r;
20 if l+1 <= r then
21 begin
22 tree[now].lc := tot+1;
23 build(l,(l+r) div 2);
24 tree[now].rc := tot+1;
25 build((l+r) div 2+1,r);
26 tree[now].dat := tree[tree[now].lc].dat+tree[tree[now].rc].dat;
27 end
28 else
29 tree[now].dat := a[l];
30 end;
31
32 procedure init;
33 var
34 i: longint;
35 begin
36 readln(n,q);
37 for i := 1 to n do read(a[i]);
38 readln;
39 build(1,n);
40 end;
41
42 procedure ins(v, x, y: longint;d: int64);
43 begin
44 if (x = tree[v].x) and (tree[v].y = y) then
45 begin
46 tree[v].last := tree[v].last+d;
47 exit;
48 end;
49 tree[v].dat := tree[v].dat+(y-x+1)*d;
50 if tree[tree[v].lc].y >= y then ins(tree[v].lc,x,y,d)
51 else
52 if tree[tree[v].rc].x <= x then ins(tree[v].rc,x,y,d)
53 else
54 begin
55 ins(tree[v].lc,x,tree[tree[v].lc].y,d);
56 ins(tree[v].rc,tree[tree[v].rc].x,y,d);
57 end;
58 end;
59
60 procedure find(v, x, y: longint);
61 begin
62 if tree[v].last <> 0 then
63 begin
64 tree[tree[v].lc].last := tree[tree[v].lc].last+tree[v].last;
65 tree[tree[v].rc].last := tree[tree[v].rc].last+tree[v].last;
66 tree[v].dat := tree[v].dat+(tree[v].y-tree[v].x+1)*tree[v].last;
67 tree[v].last := 0;
68 end;
69 if (x = tree[v].x) and (tree[v].y = y) then
70 begin
71 ans := ans+tree[v].dat;
72 exit;
73 end;
74 if tree[tree[v].lc].y >= y then find(tree[v].lc,x,y)
75 else
76 if tree[tree[v].rc].x <= x then find(tree[v].rc,x,y)
77 else
78 begin
79 find(tree[v].lc,x,tree[tree[v].lc].y);
80 find(tree[v].rc,tree[tree[v].rc].x,y);
81 end;
82 end;
83
84 procedure work;
85 var
86 i, x, y: longint;
87 d: int64;
88 ch: char;
89 begin
90 for i := 1 to q do
91 begin
92 read(ch);
93 case ch of
94 'Q': begin
95 readln(x,y);
96 ans := 0;
97 find(1,x,y);
98 writeln(ans);
99 end;
100 'C': begin
101 readln(x,y,d);
102 ins(1,x,y,d);
103 end;
104 end;
105 end;
106 end;
107
108 begin
109 init;
110 work;
111 end.
优美版(推荐)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN=600000;

struct node
{
int rc,lc,x,y;
long long dat,yan;
}tree[MAXN];
int n,q,tot;
long long ans;
long long sum[MAXN];

void Build(int l,int r)
{
int now=++tot;
tree[now].x=l,tree[now].y=r;
tree[now].dat=sum[r]-sum[l-1];
if (tree[now].x+1<=tree[now].y)
{
tree[now].lc=tot+1;
Build(l,(l+r)/2);
tree[now].rc=tot+1;
Build((l+r)/2+1,r);
}
}

void Lazy(int v)
{
if (tree[v].yan)
{
int temp=tree[v].lc;
tree[temp].dat+=tree[v].yan*(tree[temp].y-tree[temp].x+1);
tree[temp].yan+=tree[v].yan;
temp=tree[v].rc;
tree[temp].dat+=tree[v].yan*(tree[temp].y-tree[temp].x+1);
tree[temp].yan+=tree[v].yan;
}
tree[v].yan=0;
}

void Insert(int v,int a,int b,int c)
{
Lazy(v);
if (tree[v].x==a && tree[v].y==b)
{
tree[v].dat+=c*(tree[v].y-tree[v].x+1);
tree[v].yan+=c;
return;
}
if (tree[tree[v].lc].y>=b) Insert(tree[v].lc,a,b,c); else
if (tree[tree[v].rc].x<=a) Insert(tree[v].rc,a,b,c); else
{
Insert(tree[v].lc,a,tree[tree[v].lc].y,c);
Insert(tree[v].rc,tree[tree[v].rc].x,b,c);
}
tree[v].dat=tree[tree[v].lc].dat+tree[tree[v].rc].dat;
}

void Find(int v,int a,int b)
{
Lazy(v);
//printf("%d %d %d %d\n",a,b,tree[v].x,tree[v].y);
if (tree[v].x==a && tree[v].y==b)
{
ans+=tree[v].dat;
//printf("%d\n",tree[v].dat);
return;
}
if (tree[tree[v].lc].y>=b) Find(tree[v].lc,a,b); else
if (tree[tree[v].rc].x<=a) Find(tree[v].rc,a,b); else
{
Find(tree[v].lc,a,tree[tree[v].lc].y);
Find(tree[v].rc,tree[tree[v].rc].x,b);
}
}

int main()
{
int x,a,b,c;
char ch;
scanf("%d%d",&n,&q);
for (int i=1;i<=n;++i)
{
scanf("%d",&x);
sum[i]=sum[i-1]+x;
}
Build(1,n);
scanf("%c",&ch);
for (int i=1;i<=q;++i)
{
scanf("%c",&ch);
if (ch=='C')
{
scanf("%d%d%d%c",&a,&b,&c,&ch);
Insert(1,a,b,c);
}
if (ch=='Q')
{
scanf("%d%d%c",&a,&b,&ch);
ans=0;
Find(1,a,b);
printf("%I64d\n",ans);
}
}
return 0;
}



你可能感兴趣的:(Integer)