poj 3468 A Simple Problem with Integers

果的线段树,需要用到lazy-tag的方法,朴素果断超时

朴素线段树
#include <stdio.h>

const int N= 105100;

struct Node
{
    
int left, right;
    __int64 sum, add;
}node[
4*N];

int num, n, q;
__int64 data[N];
char str[1];

void swap(int &a, int &b)
{
    
int t= a;
    a
= b;
    b
= t;
}

void build_tree(int left, int right, int p)
{
    node[p].left
=left;
    node[p].right
=right;
    node[p].add
=0;
    
if ( left < right )
    {
        
int mid= left+right>>1;
        build_tree(left, mid, 
2*p);
        build_tree(mid
+1, right, 2*p+1);
        node[p].sum
= node[2*p].sum+node[2*p+1].sum;
    }
    
else if ( left == right )
        node[p].sum
= data[left];
}

void update(int p)
{
    node[p
<<1].sum+= node[p].add*(node[p<<1].right-node[p<<1].left+1);
    node[(p
<<1)+1].sum+= node[p].add*(node[(p<<1)+1].right-node[(p<<1)+1].left+1);
    node[p
<<1].add+= node[p].add;
    node[(p
<<1)+1].add+= node[p].add;
    node[p].add
= 0;
}

__int64 query(
int s, int t, int p)
{
    __int64 sum
= 0, i= 0, j= 0;
    
if ( s <= node[p].left && node[p].right <= t)
        
return node[p].sum;
    
if ( node[p].add)
        update(p);
    
int mid= node[p].right+node[p].left>>1;
    
if ( s <= mid )
        i 
= query(s, t, p<<1);
    
if ( t > mid )
        j 
= query(s, t, (p<<1)+1);
    
return i+j;
}

void adds(int s, int t, __int64 add, int p)
{
    
if ( s <= node[p].left && node[p].right <= t)
    {
        node[p].add
+=add;
        node[p].sum
+=add*(node[p].right-node[p].left+1);
        
return;
    }
    
if ( node[p].add)
        update(p);
    
int mid= node[p].right+node[p].left>>1;
    
if ( s <= mid )
        adds( s, t, add, p
<<1);
    
if ( t > mid )
        adds( s, t, add, (p
<<1)+1);
    node[p].sum
= node[p<<1].sum+node[(p<<1)+1].sum;
}

int main()
{
    scanf(
"%d%d"&n, &q);
    
int i, left, right;
    __int64 value;
    data[
0]= 0;
    
for ( i = 1 ; i <= n ; i++ )
        scanf(
"%I64d", data+i);
    build_tree(
1, n, 1);
    
while ( q-- )
    {
        scanf(
"%s", str);
        
if ( 'Q' == str[0] )
        {
            scanf(
"%d%d"&left, &right);
            printf(
"%I64d\n", query(left, right, 1));
        }
        
else
        {
            scanf(
"%d%d%I64d"&left, &right, &value);
            
if ( left > right )
                swap(left, right);
            
if ( value )
                adds(left, right, value, 
1);
        }
    }
    
return 0;
}

zkw线段树
#include <stdio.h>

const int N= 105100;

struct Node
{
    
int left, right;
    __int64 sum, add;
}node[
4*N];

int num, n, q;
__int64 data[N];
char str[10];

void build_tree()
{
    
int i;
    
for ( i = 2*num-1 ; i >= num ; i-- )
    {
        
if ( i-num > n)
            node[i].sum
= 0;
        
else
            node[i].sum
= data[i-num];
        node[i].left
= node[i].right= i-num;
        node[i].add
= 0;
    }
    
while ( i > 0 )
    {
        node[i].sum
=node[i<<1].sum+node[(i<<1)+1].sum;
        node[i].left
= node[i<<1].left;
        node[i].right
= node[(i<<1)+1].right;
        node[i].add
= 0;
        i
--;
    }
}

__int64 query(
int s, int t)
{
    __int64 sum
= 0;
    
int num_s= 0, num_t= 0;
    
for ( s= s+num-1, t= t+num+1 ; s^t^1 ; s>>=1, t>>=1 )
    {
        
if (~s&1)
        {
            sum
+=node[s^1].sum;
            num_s
+= node[s^1].right-node[s^1].left+1;
        }
        
if ( t&1 )
        {
            sum
+=node[t^1].sum;
            num_t
+= node[t^1].right-node[t^1].left+1;
        }
        sum
+=node[s>>1].add*num_s;
        sum
+=node[t>>1].add*num_t;
    }
    
for (s>>=1 ; s > 0 ; s>>=1 )
        sum
+=node[s].add*(num_s+num_t);
    
return sum;
}

void add(int s, int t, __int64 d)
{
    
int num_s= 0, num_t= 0;
    
for ( s= s+num-1, t= t+num+1 ; s^t^1 ; s>>=1, t>>=1 )
    {
        
if (~s&1)
        {
            node[s
^1].add+= d;
            node[s
^1].sum+=(node[s^1].right-node[s^1].left+1)*d;
            num_s
+= node[s^1].right-node[s^1].left+1;
        }
        
if ( t&1 )
        {
            node[t
^1].add+= d;
            node[t
^1].sum+=(node[t^1].right-node[t^1].left+1)*d;
            num_t
+= node[t^1].right-node[t^1].left+1;
        }
        node[s
>>1].sum+=d*num_s;
        node[t
>>1].sum+=d*num_t;
    }
    
for (s>>=1 ; s > 0 ; s>>=1 )
        node[s].sum
+=d*(num_s+num_t);
}

int main()
{
    scanf(
"%d%d"&n, &q);
    
int i, left, right;
    __int64 value;
    data[
0]= 0;
    
for ( i = 1 ; i <= n ; i++ )
        scanf(
"%I64d", data+i);
    
for ( num = 1 ; num < (n+2) ; num<<=1 );
    build_tree();
    
while ( q-- )
    {
        scanf(
"%s", str);
        
if ( 'Q' == str[0] )
        {
            scanf(
"%d%d"&left, &right);
            printf(
"%I64d\n", query(left, right));
        }
        
else
        {
            scanf(
"%d%d%I64d"&left, &right, &value);
            
if ( value )
                add(left, right, value);
        }
    }
    
return 0;
}

posted on 2011-09-14 15:27 purplest 阅读(142) 评论(0)  编辑 收藏 引用 所属分类: 线段树


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年9月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

导航

统计

常用链接

留言簿

随笔分类(70)

随笔档案(68)

ACMer

搜索

最新随笔

最新评论