poj3468 A Simple Problem with Integers(线段树)

A Simple Problem with Integers
Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 60462 Accepted: 18430
Case Time Limit: 2000MS

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
/*
更新
Time:2015-1-18 20:33
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
typedef long long LL;
const int MAX=100000+10;
struct Tree{
    LL nSum,ad;
}tree[MAX<<2];
void Build(int l,int r,int rt){
    tree[rt].nSum=0;tree[rt].ad=0;
    if(l==r)return;
    int mid=(l+r)>>1;
    Build(lson);
    Build(rson);
}
void Insert(int pos,LL val,int l,int r,int rt){
    if(l==r){
        tree[rt].nSum=val;
        return;
    }
    tree[rt].nSum+=val;
    int mid=(l+r)>>1;
    if(pos<=mid)
        Insert(pos,val,lson);
    else if(pos>mid)
        Insert(pos,val,rson);
}
void Add(int L,int R,LL val,int l,int r,int rt){
    if(L==l&&R==r){
        tree[rt].ad+=val;
        return;
    }
    tree[rt].nSum+=(R-L+1)*val;
    
    int mid=(l+r)>>1;
    if(R<=mid){
        Add(L,R,val,lson);
    }else if(L>mid){
        Add(L,R,val,rson);
    }else{
        Add(L,mid,val,lson);
        Add(mid+1,R,val,rson);
    }
}
LL Query(int L,int R,int l,int r,int rt){
    if(L==l&&R==r){
        return tree[rt].ad*(r-l+1)+tree[rt].nSum;
    }

    tree[rt].nSum+=tree[rt].ad*(r-l+1);

    int mid=(l+r)>>1;
    Add(l,mid,tree[rt].ad,lson);
    Add(mid+1,r,tree[rt].ad,rson);
    tree[rt].ad=0;

    if(R<=mid){
       return Query(L,R,lson);
    }else if(L>mid){
       return Query(L,R,rson);
    }else{
       return Query(L,mid,lson)+
       Query(mid+1,R,rson);
    }
}
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        int pos;
        LL val;
        memset(tree,0,sizeof(tree));
        Build(1,n,1);
        for(int i=1;i<=n;i++){
            scanf("%lld",&val);
            Insert(i,val,1,n,1);
        }
        /*
        for(int i=1;i<=n*2+1;i++){
            printf(" %d",tree[i].ad);
        }puts("");
        */
        char cmd[10];
        int L,R;
        while(m--){
            scanf("%s",cmd);
            if(cmd[0]=='Q'){
                scanf("%d%d",&L,&R);
                printf("%lld\n",Query(L,R,1,n,1));
            }else{
                scanf("%d%d%lld",&L,&R,&val);
                Add(L,R,val,1,n,1);
            }
        }
    }
return 0;
}

<span style="font-family: Arial, Helvetica, sans-serif;">/*</span>
题目大意:给n个数字,查询求区间和以及区间修改
关键:线段树的应用 数据用 long long 型
Time:2014-8-4 13:16
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAX=100000+10;
struct CNode
{
     int L,R;
     long long nSum,lnc;
     int Mid()
     {return (L+R)/2;}
}Tree[4*MAX];
void BuildTree(int Root,int L,int R)
{                                                           
     Tree[Root].L=L;
     Tree[Root].R=R;
     Tree[Root].nSum=0;
     Tree[Root].lnc=0;
     if(L==R)return ;
     BuildTree(Root*2+1,L,Tree[Root].Mid());
     BuildTree(Root*2+2,Tree[Root].Mid()+1,R);
}                                     
void Insert(int Root,int pos,long long v)
{
     if(Tree[Root].L==pos&&Tree[Root].R==pos)//也可以L==R 
     {
     Tree[Root].nSum=v;//Root.lnc=v;
     return;
     }
     Tree[Root].nSum+=v;
     if(pos<=Tree[Root].Mid())
       Insert(Root*2+1,pos,v);
     else
       Insert(Root*2+2,pos,v);
}
void Add(int Root,int a,int b,long long c)
{
     if (Tree[Root].L==a&&Tree[Root].R==b)
     {
        Tree[Root].lnc+=c;
        return;
     }
     Tree[Root].nSum+=(b-a+1)*c;//此处应该为 c 不是 lnc 此处出错 
     if(b<=Tree[Root].Mid())
        Add(Root*2+1,a,b,c);
     else if(a>=Tree[Root].Mid()+1)
     {
        Add(Root*2+2,a,b,c); 
     }
     else
     {
         Add(Root*2+1,a,Tree[Root].Mid(),c);
         Add(Root*2+2,Tree[Root].Mid()+1,b,c);    
     }   
}
long long QuerynSum(int Root,int s,int e)
{
    if(Tree[Root].L==s&&Tree[Root].R==e)
    {
       return Tree[Root].nSum+(Tree[Root].R-Tree[Root].L+1)*Tree[Root].lnc;                     
    }
    Tree[Root].nSum+=(Tree[Root].R-Tree[Root].L+1)*Tree[Root].lnc;
    Add(Root*2+1,Tree[Root].L,Tree[Root].Mid(),Tree[Root].lnc);
    Add(Root*2+2,Tree[Root].Mid()+1,Tree[Root].R,Tree[Root].lnc);
    Tree[Root].lnc=0;
    if(e<=Tree[Root].Mid())
       return QuerynSum(Root*2+1,s,e);
    else if(s>=Tree[Root].Mid()+1)
       return QuerynSum(Root*2+2,s,e);
    else
    {
        return 
        QuerynSum(Root*2+1,s,Tree[Root].Mid())+
        QuerynSum(Root*2+2,Tree[Root].Mid()+1,e);
        
    }      
}
int main()
{
    int N,q;
    while(scanf("%d%d",&N,&q)!=EOF)
    {                              
         memset(Tree,0,sizeof(Tree));
         BuildTree(0,1,N);
         for(int i=1;i<=N;i++)
         {
           long long v;
         scanf("%lld",&v); 
         Insert(0,i,v); 
         }
         /*
         for(int i=0;i<=4*N;i++)
         printf("%d %d\n",Tree[i].L,Tree[i].R);
         */
         char cmd[10];
         while(q--)
         {
            scanf("%s",cmd);
            if(cmd[0]=='Q')
            {
               int s,e;
               scanf("%d%d",&s,&e);
               printf("%lld\n",QuerynSum(0,s,e)); //long long 型              
            }
            else
            {
                int a,b;
                long long c;
                scanf("%d%d%lld",&a,&b,&c);
                Add(0,a,b,c);    
            }       
         }
                                                                 
    }
return 0;    
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值