poj3468(线段树||树状数组)

来源:互联网 发布:淘宝宝贝视频制作 编辑:程序博客网 时间:2024/06/08 09:12
//成段更新线段树即可#include <iostream>#include "stdio.h"#include "stdlib.h"#include "string.h"#include "algorithm"#include <queue>#define N 100005using namespace std;struct node {    long long int data,lazy;    int left,right;}ss[N<<2];void pushdown(int k,int len){    if(ss[k].lazy)    {        ss[k<<1].lazy+=ss[k].lazy;        ss[k<<1|1].lazy+=ss[k].lazy;        ss[k<<1].data+=ss[k].lazy*(len-(len>>1));        ss[k<<1|1].data+=ss[k].lazy*(len>>1);        ss[k].lazy=0;    }}void buildtree(int k,int l,int r){    ss[k].lazy=0;    ss[k].left=l;ss[k].right=r;    if(l==r) {        scanf("%lld",&ss[k].data);        return;    }    int mid=(l+r)>>1;    buildtree(k<<1,l,mid);    buildtree(k<<1|1,mid+1,r);    ss[k].data=ss[k<<1].data+ss[k<<1|1].data;}void update(int k,int ll,int rr,int c){    if(ll<=ss[k].left&&rr>=ss[k].right)    {        ss[k].lazy+=c;        ss[k].data+=c*(ss[k].right-ss[k].left+1);        return;    }    pushdown(k,ss[k].right-ss[k].left+1);    int mid=(ss[k].left+ss[k].right)>>1;    if(ll <= mid)        update(k<<1,ll,rr,c);    if(rr > mid)        update(k<<1|1,ll,rr,c);    ss[k].data=ss[k<<1].data+ss[k<<1|1].data;}long long int  query(int k,int ll,int rr){    if(ll<=ss[k].left&&rr>=ss[k].right)        return ss[k].data;    pushdown(k,ss[k].right-ss[k].left+1);    long long int ans=0;    int m=(ss[k].left+ss[k].right)>>1;    if(ll <=m)        ans+= query(k<<1, ll, rr);    if(rr >m)        ans+= query(k<<1|1, ll, rr);    return ans;}int main(){    int n,q,op,ed,change;    long long int   tmp;    char choice[10];    //freopen("t","r",stdin);    scanf("%d%d",&n,&q);    buildtree(1,1,n);    while(q--)    {        scanf("%s",choice);        if(choice[0]=='Q') {            scanf("%d%d",&op,&ed);            printf("%lld\n",query(1,op,ed));        }        else if(choice[0]=='C'){            scanf("%d%d%d",&op,&ed,&change);            update(1,op,ed,change);        }    }    return 0;}
////  main.c//  example////  Created by Adam on 15/2/2.//  Copyright (c) 2015年 Adam. All rights reserved.//// 树状数组成段更新元素// 首先我们开个数组 ans[i] 表示原序列前i个元素的总和 那么原序列区间[a,b]的总和 ans(a,b) = ans[b]-ans[a];// sum[i] 表示对序列进行更改后前i个元素的总和// 我们再开个数组 c1[i]表示 区间[i,n]的每个元素都改变的值// 例如现在给区间[a,b]每个元素都加上c 只需要对c1这个数组进行更改 c1[a] += c; c1[b+1] -= c;// sum[a] = ans[a] + c1[1]*a + c1[2]*(a-1) + c1[i]*(a-i+1) + ..... + c1[a]*1;// sum[a] = ans[a] +   c1[i]*(a-i+1)  (1<=i<=a)// sum[a] = ans[a] + c1[i]*(a+1)-ci[i]*i (1<=i<=a)// 那么区间[a,b]的总和 sum(a,b) = sum[b] - sum[a]//                   sum[a] = ans[a] + c1[i]*(a+1)-ci[i]*i (1<=i<=a)//                   sum[b] = ans[b] + c1[i]*(b+1)-ci[i]*i (1<=i<=b)////                   sum(a,b) = sum[b] - sum[a]//                            = ans[b] + c1[i]*(b+1)-ci[i]*i (1<=i<=b) -//                                ( ans[a] + c1[i]*(a+1)-ci[i]*i (1<=i<=a) )#include <iostream>#include "stdio.h"#include "stdlib.h"#include "string.h"#include "algorithm"#include <queue>#define N 100005using namespace std;long long int sum[N];long long int c1[N];long long int c2[N];int n,q;int lowbit(int x){    return x & (-x);}void update(int k, int change, long long int *c){    while(k <= n)    {        c[k] += change;        k += lowbit(k);    }}long long int query(int k, long long int *c){    long long int ans=0;    while(k)    {        ans += c[k];        k -= lowbit(k);    }    return ans;}int main(){    int a,b,c;    char choice[2];        scanf("%d %d", &n, &q);    memset(c1, 0, sizeof c1);    memset(c2, 0, sizeof c2);    for(int i=1;i<=n;i++)    {        scanf("%lld",&sum[i]);        sum[i]+=sum[i-1];    }    while(q--)    {        scanf("%s", choice);        if(choice[0] == 'Q'){            scanf("%d %d", &a, &b);            printf("%lld\n",sum[b]-sum[a-1]+(b+1)*query(b, c1)-a*query(a-1, c1)-query(b, c2)+query(a-1, c2));        }        else{            scanf("%d %d %d", &a, &b, &c);            update( a, c, c1);            update( b+1, -c, c1);            update( a, c*a, c2);            update( b+1, -c*(b+1), c2);                    }    }    return 0;}


0 0
原创粉丝点击