poj 3468 A Simple Problem with Integers 解题报告 线段树 数状数组两种实现

来源:互联网 发布:阿里云推荐码2017 编辑:程序博客网 时间:2024/04/27 23:05
A Simple Problem with Integers
Time Limit: 5000MS Memory Limit: 131072KTotal Submissions: 43907 Accepted: 12862Case Time Limit: 2000MS

Description

You have N integers, A1A2, ... , 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 A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

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

Sample Input

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

Sample Output

455915

Hint

The sums may exceed the range of 32-bit integers.
这和上一题基本上是一致的,只是在细节上注意,在QUERY()函数里面,也是要把延迟的标记,更新的,一定要注意!些外这题是要用INT64的!
#include <iostream>#include <stdio.h>using namespace std;#define N 111111__int64 l[N<<2],flag[N<<2];void build(__int64 num,__int64 s,__int64 e){      flag[num]=0;      if(s==e)      {            scanf("%I64d",&l[num]);            return ;      }      __int64 mid=(s+e)>>1;      build(num<<1,s,mid);      build(num<<1|1,mid+1,e);      l[num]=l[num<<1]+l[num<<1|1];}void update(__int64 num ,__int64 s,__int64 e,__int64 a, __int64 b,__int64 c){      if(a<=s&&b>=e)      {            flag[num]+=c;            l[num]+=(e-s+1)*c;            return ;      }      if(flag[num])      {            flag[num<<1]+=flag[num];            flag[num<<1|1]+=flag[num];            l[num<<1]+=(e-s+1-((e-s+1)>>1))*flag[num];            l[num<<1|1]+=((e-s+1)>>1)*flag[num];            flag[num]=0;      }      __int64 mid=(s+e)>>1;      if(mid>=a)      {            update(num<<1,s,mid,a,b,c);      }      if(b>mid)      {            update(num<<1|1,mid+1,e,a,b,c);      }      l[num]=l[num<<1]+l[num<<1|1];}__int64 query(__int64 num,__int64 s,__int64 e ,__int64 a,__int64 b){      if(a<=s&&b>=e)      {            return l[num];      }      if(flag[num])      {            flag[num<<1]+=flag[num];            flag[num<<1|1]+=flag[num];            l[num<<1]+=(e-s+1-((e-s+1)>>1))*flag[num];            l[num<<1|1]+=((e-s+1)>>1)*flag[num];            flag[num]=0;      }      __int64 mid=(s+e)>>1;      __int64 re=0;      if(mid>=a)re+=query(num<<1,s,mid,a,b);      if(mid<b) re+=query(num<<1|1,mid+1,e,a,b);      return re;}int  main(){      __int64 n,q,a,b,d;      char c;    while(scanf("%I64d%I64d",&n,&q)!=EOF)    {          build(1,1,n);          while(q--)          {                getchar();                if((c=getchar())=='Q')                {                    scanf("%I64d%I64d",&a,&b);                    printf("%I64d\n",query(1,1,n,a,b));                }                else if(c=='C')                {                      scanf("%I64d%I64d%I64d",&a,&b,&d);                      update(1,1,n,a,b,d);                }          }    }    return 0;}
这题用树状数组来做,更加简单的多,原理当然还是一样,只是树状数组写的更简单,毫无疑问,用树状数组,更加省空间,不会出现像线段树那样一搞就爆了内存!

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;#define MAXN 50005int prime[MAXN],tree[12][12][MAXN],n;int lowbit(int x){    return x&(-x);}int update(int i,int j,int x,int c){    if(x==0)    return -1;    while(x<=n)    {        tree[i][j][x]+=c;        x=x+lowbit(x);    }    return -1;}int getsum(int i,int j,int x){    int sum=0;    while(x>0)    {        sum+=tree[i][j][x];        x=x-lowbit(x);    }    return sum;}int main (){    int i,asknum,ask,pos,sum,a,b,k,c;    while(scanf("%d",&n)!=EOF)    {        memset(tree,0,sizeof(tree));        for(i=1;i<=n;i++)        {            scanf("%d",&prime[i]);        }        scanf("%d",&asknum);        while(asknum--)        {            scanf("%d",&ask);            if(ask==1)            {                scanf("%d%d%d%d",&a,&b,&k,&c);                int kk=(b-a)/k;                update(k,a%k,a,c);                update(k,a%k,b+1,-c);            }            else            {                scanf("%d",&pos);                sum=prime[pos];                for(i=1;i<=10;i++)                {                    sum+=getsum(i,pos%i,pos);                }                printf("%d\n",sum);            }        }    }    return 0;}



原创粉丝点击