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; }
这是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; }
要学的东西还有很多,线段树,哎