您的位置:首页 > 其它

poj 3468 A Simple Problem with Integers

2012-04-05 16:58 260 查看
最近在研究线段树,所以就先找简单点的练练手,虽然简单,但是对于刚入手的我来说,也不简单了,对于大牛就别掺合了,谢谢了。

说说我对线段树的理解吧, 就是定义一个结构体数组, 这个结构体的属性是包含一个线段的始点和终点,以及你所需要的操作属性,比如求一段区间的和,就多定义一个属性和的变量。还有些定义和细节我就不说了。

其次就是建树的过程了,这棵树你可以理解成完全二叉树,但是实质往往不是的。之所以要那么理解是需要它的性质,它的一个结点的左儿子的编号是父节点编号的2倍,右儿子的是2倍+1。再接下来就是你所需要的操作了,查询,更新,求和,删除等。这里讲的是求和。

对于求和,这个不需要输出的操作,我们什么时候更新一段线段的和值呢?又怎么更新呢?起初这个搞得我也很困惑,后来终于搞明白了,更新分两步走的,求和的时候更新一次,另一次就是在查询了,因为时间限制,所以只需要更新所需要的线段就好。对于求和,就是便找线段便更新,假设有一棵树,中间有个你需要找的结点,找到后就依次往上更新其父节点,再父父结点...最后就是根节点啦,对于这个结点的下面就不要更新了,时间问题嘛。

对于查询比求和要简单一点,因为它不需往上更新了,只需跟新到你要找的结点就好,这个便找变更新就好。

#include<stdio.h>
#include<string>
#define MAX 100000

struct Node
{
int l, r;
__int64 sum, c;
}a[MAX*4];

void built(int l, int r, int step)
{
a[step].l = l;
a[step].r = r;
a[step].c = 0;

if(l == r)
{
scanf("%I64d", &a[step].sum);
return ;
}

int mid = (l + r)/2;

built(l, mid, step*2);
built(mid+1, r, step*2+1);

a[step].sum = a[step*2].sum + a[step*2+1].sum;
}

void add(int l,  int r, int c, int step)
{
if(l == a[step].l && r == a[step].r)
{
a[step].sum += c * (a[step].r - a[step].l + 1);
a[step].c   += c;
return;
}

if(a[step].c != 0)                                    //更新 线段和
{
a[step*2].c     += a[step].c;
a[step*2+1].c   += a[step].c;
a[step*2].sum   += a[step].c * (a[step*2].r - a[step*2].l + 1);
a[step*2+1].sum += a[step].c * (a[step*2+1].r - a[step*2+1].l + 1);
a[step].c        = 0;
}

int mid = (a[step].l + a[step].r)/2;

if(mid >= r)            add(l, r, c, step*2);
else if(mid < l)        add(l, r, c, step*2+1);
else
{
add(l, mid, c, step*2);
add(mid+1, r, c, step*2+1);
}

a[step].sum = a[step*2].sum + a[step*2+1].sum;   //递归更新所要加的线段之上的线段和
}

__int64 query(int l, int r, int step)
{
if(l == a[step].l && r == a[step].r)
{
return  a[step].sum;
}

if(a[step].c != 0)                         //往下更新,只需更新到你要找的结点就好
{
a[step*2].c     += a[step].c;
a[step*2+1].c   += a[step].c;
a[step*2].sum   += a[step].c * (a[step*2].r - a[step*2].l + 1);
a[step*2+1].sum += a[step].c * (a[step*2+1].r - a[step*2+1].l + 1);
a[step].c = 0;
}

int mid = (a[step].l + a[step].r)/2;

if(mid >= r)         return   query(l, r, step*2);
else if(mid < l)     return   query(l, r, step*2+1);
else
{
return    query(l, mid, step*2) + query(mid+1, r, step*2+1);
}
}

int main()
{
int n, m, l, r, c;
char s[10];
while(scanf("%d%d", &n, &m) != EOF)
{
built(1, n, 1);

while(m--)
{
scanf("%s", s);  //注意要接受字符串,因为上面的输入缓冲区里还有换行符

if(s[0] == 'Q')
{
scanf("%d%d", &l, &r);
printf("%I64d\n", query(l, r, 1));
}
else
{
scanf("%d%d%d", &l, &r, &c);
add(l, r, c, 1);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: