POJ 3468 线段树

Description

You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000. The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000. Each of the next Q lines represents an operation. "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000. "Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.
自己做了很久,在编译器可以通过,但是就是不能AC,也考虑到数据的大,所以尝试了用double,long double,_int64等定义变量,但是都没过,实在不行我就查了一下别人的解题报告,才知道这道题不是简单的替换更新题,二十线段树,所以我的代码当然不会通过测试点了
这是我的代码:
#include <stdio.h>
int main()
{
    long n,q;
    long i,j;
    _int64 arr[100001];
    char ch;
    _int64 a,b,c;
    scanf("%l4d%ld",&n,&q);
    for(i=1;i<=n;i++)
        scanf("%I64d",&arr[i]);
    for(i=0;i<q;i++)
    {
        _int64 sum=0;
        fflush(stdin);
        ch=getchar();
        if(ch=='Q')
        {    
            scanf("%I64d%I64d",&a,&b);
            for(j=a;j<=b;j++)
                sum+=arr[j];
            printf("%I64d\n",sum);
        }
        else if(ch=='C')
        {
            //fflush(stdin);
            scanf("%I64d%I64d%I64d",&a,&b,&c);
            for(j=a;j<=b;j++)
                arr[j]+=c;
        }
    }
    return 0;
}
View Code

这是AC代码:

#include <stdio.h>

#define DEBUG

#ifdef DEBUG
#define debug(...) printf( __VA_ARGS__) 
#else
#define debug(...)
#endif

#define N 100002

#define lowbit(i) ( i & (-i) )

/* 设delta[i]表示[i,n]的公共增量 */
long long c1[N];    /* 维护delta[i]的前缀和 */
long long c2[N];    /* 维护delta[i]*i的前缀和 */
long long sum[N];
int       A[N];
int n;

long long query(long long *array, int i)
{
    long long tmp;

    tmp = 0;
    while (i > 0) {
        tmp += array[i];
        i -= lowbit(i);
    }
    return tmp;
}

void update(long long *array, int i, long long d) 
{
    while (i <= n) {
        array[i] += d;
        i += lowbit(i);
    }
}

int main() 
{
    int         q, i, s, t, d;
    long long     ans;
    char        action;

    scanf("%d %d", &n, &q);
    for (i = 1; i <= n; i++) {
        scanf("%d", A+i);
    }
    for (i = 1; i <= n; i++) {
        sum[i] = sum[i-1] + A[i];
    }

    while (q--) {
        getchar();
        scanf("%c %d %d", &action, &s, &t);
        if (action == 'Q') {
            ans = sum[t] - sum[s-1];
            ans += (t+1)*query(c1, t) - query(c2, t);
            ans -= (s*query(c1, s-1) - query(c2, s-1));
            printf("%lld\n", ans);
        }
        else {
            scanf("%d", &d);
            /* 把delta[i](s<=i<=t)加d,策略是
             *先把[s,n]内的增量加d,再把[t+1,n]的增量减d
             */
            update(c1, s, d);
            update(c1, t+1, -d);
            update(c2, s, d*s);
            update(c2, t+1, -d*(t+1));
        }
    }
    return 0;
}
View Code

要学的东西还有很多,线段树,哎

posted on 2013-07-18 01:12  Forgiving  阅读(72)  评论(0编辑  收藏  举报