poj 3468【线段树+延迟优化】

来源:互联网 发布:java 下载图片到本地 编辑:程序博客网 时间:2024/06/07 15:46

经典线段树题目,如果用一般的深入到每个节点去修改值的方法会TLE,所以这里引入一个新名词“延迟优化”,意思是说每个节点线段有一个增量值inc,用来保存增量的,当当前区间等于要查询的区间就用当前区间的和sum+当前区间的增量inc*(t-s+1),否则就把增量传下去,而当前区间则加上这增量和并且inc 归零

由于此时poj突然没有了这题,估计要改数据,所以提交不了,先上代码。

线段树Accepted7116K1688MSC++  

int lowbit(int t){return t&(-t);}int countbit(int t){return (t==0)?0:(1+countbit(t&(t-1)));}int gcd(int a,int b){return (b==0)?a:gcd(b,a%b);}#define LL long long#define pi acos(-1)#define N  100010#define INF INT_MAX#define eps 1e-8struct node{    int l,r;    LL sum;    LL inc;}c[N*4];LL a[N];int n,m;void Build(int i,int s,int t){    c[i].l=s;    c[i].r=t;    c[i].inc=0;    if(s==t)    {        c[i].sum=a[s];//printf("!%I64d\n",a[i]);        return ;    }    if(s<t){    int mid=(s+t)>>1;    Build(2*i,s,mid);    Build(2*i+1,mid+1,t);    }    c[i].sum=c[2*i].sum+c[2*i+1].sum;}void add(int i,int s,int t,LL num){    if(c[i].l==s && c[i].r==t)    {        c[i].inc+=num;        return ;    }    c[i].sum+=(t-s+1)*num;    int mid=(c[i].l+c[i].r)>>1;    if(t<=mid)    add(2*i,s,t,num);    else    if(mid<s)    add(2*i+1,s,t,num);    else    {        add(2*i,s,mid,num);        add(2*i+1,mid+1,t,num);    }}LL query(int i,int s,int t){    LL del=c[i].inc;    if(c[i].l==s && c[i].r==t)    {        return c[i].sum+del*(t-s+1);    }    else//    {        c[2*i].inc+=c[i].inc;        c[2*i+1].inc+=c[i].inc;        c[i].sum+=del*(c[i].r-c[i].l+1);//!!!        c[i].inc=0;    }    int mid=(c[i].l+c[i].r)>>1;    if(t<=mid)    return query(2*i,s,t);    else    if(mid<s)    return query(2*i+1,s,t);    else    {        return query(2*i,s,mid) + query(2*i+1,mid+1,t);    }}int main(){    //freopen("a.txt","r",stdin);    int i,j;    while(scanf("%d%d",&n,&m)!=EOF)    {        for(i=1;i<=n;i++)            scanf("%I64d",&a[i]);        Build(1,1,n);        while(m--)        {            char str[3];            int s,t;            scanf("%s %d %d",str,&s,&t);            if(str[0]=='Q')            {                LL ans=query(1,s,t);                printf("%I64d\n",ans);            }            else            {                LL d;                scanf("%I64d",&d);                add(1,s,t,d);            }        }    }    return 0;}

树状数组:

Accepted2876K1141MSC++1883B

int lowbit(int t){return t&(-t);}int countbit(int t){return (t==0)?0:(1+countbit(t&(t-1)));}int gcd(int a,int b){return (b==0)?a:gcd(b,a%b);}#define LL long long#define pi acos(-1)#define N  100010#define INF INT_MAX#define eps 1e-8LL c1[N];    /* 维护delta[i]的前缀和 */LL c2[N];    /* 维护delta[i]*i的前缀和 */LL sum[N];int a[N];int n;LL query(LL *array, int i){    LL tmp;    tmp = 0;    while (i > 0) {        tmp += array[i];        i -= lowbit(i);    }    return tmp;}void add(LL *array, int i, LL d){    while (i <= n) {        array[i] += d;        i += lowbit(i);    }}int main(){    //freopen("a.txt","r",stdin);    int  m, i;    LL  ans;    char  str[3];    while(scanf("%d %d", &n, &m)!=EOF)    {    for (i = 1; i <= n; i++)        scanf("%d", &a[i]);    for (i = 1; i <= n; i++)        sum[i] = sum[i-1] + a[i];    while (m--)    {        scanf("%s",str);        LL s,t,d;        scanf("%I64d%I64d",&s,&t);        if (str[0] == 'Q')        {            ans = sum[t] - sum[s-1];            ans += (t+1)*query(c1, t) - query(c2, t);            ans -= s*query(c1, s-1) - query(c2, s-1);            printf("%I64d\n", ans);        }        else        {            scanf("%I64d", &d);            add(c1, s, d);            add(c1, t+1, -d);            add(c2, s, d*s);            add(c2, t+1, -d*(t+1));        }    }    }    return 0;}



原创粉丝点击