POJ -3468- A Simple Problem with Integers (线段是区间修改)

来源:互联网 发布:vscode js代码提示 编辑:程序博客网 时间:2024/06/07 15:38

                                   

 A Simple Problem with Integers

 
区间更新问题(题目链接)
这道题不同于更新单点,更新单点时间复杂度是log(n)
但是如果是区间更新就是nlog(n)
这样的处理方式是有悖于线段树的宗旨
那么如何解决?
单点更新的问题在于必须具体更新到每一个数
比如  更新区间  1 - 9 那么必须更新1-9的值。
如果可以不用更新1-9的值,那么时间复杂度至少减少一半
那么我们就在结构体里面新加一项,区间增值
如果一个区间在需要更新的区间里,那么它的子区间都需要更新,需要加上增加值
如果我们在更新的时候的时候把子区间都列出来更新了是非常费时的
那么当发现这类区间的时候,我们把区间的增加值记录在这个区间中
当查询下面的小区间时,看看上面的区间是不是有增加值,如果有,那么加上

AC代码
#include<stdio.h>#include<algorithm>#include<iostream>using namespace std;const int MAXN=100000;int num[MAXN];struct Node{    int l,r;//区间的左右端点long long nSum;//区间上的和long long Inc;//区间增量的累加}segTree[MAXN*3];void Build(int i,int l,int r){    segTree[i].l=l;    segTree[i].r=r;    segTree[i].Inc=0;    if(l==r)    {        segTree[i].nSum=num[l];        return;    }    int mid=(l+r)>>1;    Build(i<<1,l,mid);    Build(i<<1|1,mid+1,r);    segTree[i].nSum=segTree[i<<1].nSum+segTree[i<<1|1].nSum;}void Add(int i,int a,int b,long long c)//在结点i的区间(a,b)上增加c{    if(segTree[i].l==a&&segTree[i].r==b)//如果区间相等重合    {        segTree[i].Inc+=c;  //加到区间增量上        return;    }    segTree[i].nSum+=c*(b-a+1);//区间加上区间增量(从头到尾的增量)    int mid=(segTree[i].l+segTree[i].r)>>1;    if(b<=mid)  Add(i<<1,a,b,c);//缩小l r的区间    else if(a>mid)  Add(i<<1|1,a,b,c);    else//缩小a,b的区间    {        Add(i<<1,a,mid,c);        Add(i<<1|1,mid+1,b,c);    }}long long Query(int i,int a,int b)//查询a-b的总和{    if(segTree[i].l==a&&segTree[i].r==b)    {        return segTree[i].nSum+(b-a+1)*segTree[i].Inc;    }    segTree[i].nSum+=(segTree[i].r-segTree[i].l+1)*segTree[i].Inc;    int mid=(segTree[i].l+segTree[i].r)>>1;    Add(i<<1,segTree[i].l,mid,segTree[i].Inc);    Add(i<<1|1,mid+1,segTree[i].r,segTree[i].Inc);    segTree[i].Inc=0;    if(b<=mid)  return Query(i<<1,a,b);    else if(a>mid)  return Query(i<<1|1,a,b);    else return Query(i<<1,a,mid)+Query(i<<1|1,mid+1,b);}int main(){    int n,q;    int i;    int a,b,c;    char ch;    while(scanf("%d%d",&n,&q)!=EOF)    {        for(i=1;i<=n;i++)  scanf("%d",&num[i]);        Build(1,1,n);        for(i=1;i<=q;i++)        {            cin>>ch;            if(ch=='C')            {                scanf("%d%d%d",&a,&b,&c);                Add(1,a,b,c);            }            else            {                scanf("%d%d",&a,&b);fff                printf("%I64d\n",Query(1,a,b));            }        }    }    return 0;}



阅读全文
0 0
原创粉丝点击