POJ 3468 A Simple Problem with Integers(线段树)

来源:互联网 发布:央视网络黄金裴蕾 编辑:程序博客网 时间:2024/05/16 09:09

这题刚开始用的普通的累加方法,果断超时...中间做些小改变就行了,还有就是结果要用long long 



题目链接 点击打开链接


代码注释:


<strong><span style="font-size:18px;color:#ff6600;">#include<iostream>#include<cstdio>#define N 100000using namespace std;int s[N+5];struct node{    int l,r;    long long sum,n; //数比较大用 long long} a[N*3];void build(int l,int r,int i){    a[i].l=l;    a[i].r=r;    a[i].n=0;    if(l==r)    {        a[i].sum=s[l];        return ;    }    int mid=(l+r)/2;    build(l,mid,2*i);    build(mid+1,r,2*i+1);    a[i].sum=a[2*i].sum+a[2*i+1].sum;//向上更新}void insert(int l,int r,int c,int i){    if(a[i].l==l&&a[i].r==r)    {        a[i].n+=c;        return;    }    a[i].sum+=(long long)c*(r-l+1); //更新时把每段的总和算出来    int mid=(a[i].l+a[i].r)/2;    if(r<=mid)        insert(l,r,c,2*i);    else if(l>mid)        insert(l,r,c,2*i+1);    else    {        insert(l,mid,c,2*i);        insert(mid+1,r,c,2*i+1);    }}long long cal(int l,int r,int i){    if(a[i].l==l&&a[i].r==r)        return a[i].sum+(long long)(r-l+1)*a[i].n;    if(a[i].n!=0)  // 本题关键就在这,相当于把权值向下传递    {        a[2*i].n+=a[i].n;        a[2*i+1].n+=a[i].n;        a[i].sum+=(long long)(a[i].r-a[i].l+1)*a[i].n;//同上算出每段的sum,最后加起来方便        a[i].n=0;    }    int mid=(a[i].l+a[i].r)/2;    if(r<=mid)        return cal(l,r,2*i);    else if(l>mid)        return cal(l,r,2*i+1);    else        return cal(l,mid,2*i)+cal(mid+1,r,2*i+1);}int main(){    int n,m,x,y,i,c;    while(scanf("%d%d",&n,&m)!=EOF)//用cin可能超时    {        for(i=1; i<=n; i++)            scanf("%d",&s[i]);        build(1,n,1);        char o;        while(m--)        {            getchar(); //这里不要忘了...            scanf("%c",&o);            if(o=='Q')            {                scanf("%d%d",&x,&y);                printf("%lld\n",cal(x,y,1));            }            else            {                scanf("%d%d%d",&x,&y,&c);                insert(x,y,c,1);            }        }    }}</span></strong>


0 0
原创粉丝点击