XTU1238:Segment Tree(线段树区间更新)

来源:互联网 发布:淘宝篮球鞋进货渠道 编辑:程序博客网 时间:2024/06/03 12:29

Segment Tree

   Accepted : 98 Submit : 545Time Limit : 9000 MS Memory Limit : 65536 KB

Segment Tree

Problem Description:

A contest is not integrity without problems about data structure.

There is an array a[1],a[2],…,a[n]. And q questions of the following 4 types:
  • 1 l r c - Update a[k] with a[k]+c for all l≤k≤r
  • 2 l r c - Update a[k] with min{a[k],c} for all l≤k≤r;
  • 3 l r c - Update a[k] with max{a[k],c} for all l≤k≤r;
  • 4 l r - Ask for min{a[k]:l≤k≤r} and max{a[k]:l≤k≤r}.

Input

The first line contains a integer T(no more than 5) which represents the number of test cases.

For each test case, the first line contains 2 integers n,q (1≤n,q≤200000).

The second line contains n integers a1,a2,…,an which indicates the initial values of the array (|ai|≤).

Each of the following q lines contains an integer t which denotes the type of i-th question. If t=1,2,3, 3 integers l,r,c follows. If t=4, 2 integers l,r follows. (1≤ti≤4,1≤li≤ri≤n)

If t=1, |ci|≤2000;

If t=2,3, |ci|≤10^9.

Output

For each question of type 4, output two integers denote the minimum and the maximum.

Sample Input

1
1 1
1
4 1 1

Sample Output

1 1


题目链接:http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1238

题目大意:自己看;

题目分析:线段树区间更新,区间求值;

我的初始错误代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int maxn=222222;ll minv[maxn*8],maxv[maxn*8],num[maxn*8],smin[maxn*8],smax[maxn*8],addv[maxn*8];int n,p;ll _maxv,_minv;void maintain(int o,int l,int r){    int lc=o<<1,rc=o<<1|1;    if(l==r)        return ;    minv[o]=min(minv[lc],minv[rc]);    maxv[o]=max(maxv[lc],maxv[rc]);}void build(int o,int l,int r){    int lc=o<<1,rc=o<<1|1;    if(l==r)    {        minv[o]=maxv[o]=num[l];        return ;    }    int m=(l+r)>>1;    build(lc,l,m);    build(rc,m+1,r);    maintain(o,l,r);}void pushdown(int o,int l,int r){    if(l==r)        return ;    int lc=o<<1,rc=o<<1|1;    if(addv[o])    {        minv[lc]+=addv[o];        minv[rc]+=addv[o];        addv[lc]+=addv[o];        addv[rc]+=addv[o];        maxv[lc]+=addv[o];        maxv[rc]+=addv[o];        addv[o]=0;    }    if(smax[o])    {        smax[lc]=smax[rc]=smax[o];        minv[lc]=max(minv[lc],smax[o]); minv[rc]=max(minv[rc],smax[o]);        maxv[rc]=max(maxv[rc],smax[o]); maxv[lc]=max(maxv[lc],smax[o]);        smax[o]=0;    }    if(smin[o])    {        smin[lc]=smin[rc]=smin[o];        minv[lc]=min(minv[lc],smin[o]);  minv[rc]=min(minv[rc],smin[o]);        maxv[rc]=min(maxv[rc],smin[o]);  maxv[lc]=min(maxv[lc],smin[o]);        smin[o]=0;    }}void unreduce(int o,int l,int r,int L,int R,ll c){    int m=(l+r)>>1;    int lc=o<<1,rc=o<<1|1;    pushdown(o,l,r);    if(l>=L&&r<=R)    {        smax[o]=c;        minv[o]=max(minv[o],c);        maxv[o]=max(maxv[o],c);        return ;    }    if(L<=m)        unreduce(lc,l,m,L,R,c);    if(R>m)        unreduce(rc,m+1,r,L,R,c);    maintain(o,l,r);}void reduce(int o,int l,int r,int L,int R,ll c){    int m=(l+r)>>1;    int lc=o<<1,rc=o<<1|1;    pushdown(o,l,r);    if(l>=L&&r<=R)    {        smin[o]=c;        minv[o]=min(minv[o],c);        maxv[o]=min(maxv[o],c);        return ;    }    if(L<=m)        reduce(lc,l,m,L,R,c);    if(R>m)        reduce(rc,m+1,r,L,R,c);    maintain(o,l,r);}void add(int o,int l,int r,int L,int R,ll c){    int m=(l+r)>>1;    int lc=o<<1,rc=o<<1|1;     pushdown(o,l,r);    if(l>=L&&r<=R)    {        addv[o]+=c;        minv[o]+=c;        maxv[o]+=c;        return ;    }    if(L<=m)        add(lc,l,m,L,R,c);    if(R>m)        add(rc,m+1,r,L,R,c);    maintain(o,l,r);}void query(int o,int l,int r,int L,int R){    int m=(l+r)>>1;    int lc=o<<1,rc=o<<1|1;    pushdown(o,l,r);    if(l>=L&&r<=R)    {        _minv=min(_minv,minv[o]);        _maxv=max(_maxv,maxv[o]);        return ;    }    if(L<=m)        query(lc,l,m,L,R);    if(R>m)        query(rc,m+1,r,L,R);    maintain(o,l,r);}int main(){    int T;    while(scanf("%d",&T)!=EOF)    while(T--)    {        memset(addv,0,sizeof(addv));        memset(smin,0,sizeof(smin));        memset(smax,0,sizeof(smax));        scanf("%d%d",&n,&p);        for(int i=1;i<=n;i++)        {             scanf("%I64d",&num[i]);        }        build(1,1,n);        int l,r;        ll c;        for(int i=0;i<p;i++)        {            int t;            scanf("%d%d%d",&t,&l,&r);            if(t==4)            {                _minv=1e12+7;                _maxv=-1e12+7;                query(1,1,n,l,r);                printf("%I64d %I64d\n",_minv,_maxv);                continue;            }            scanf("%I64d",&c);            if(t==1)            {                add(1,1,n,l,r,c);            }            if(t==2)            {                reduce(1,1,n,l,r,c);            }            if(t==3)            {                unreduce(1,1,n,l,r,c);            }        }    }    return 0;}

这份代码错误的地方有:

    当操作2,3时,有覆盖操作;

  比如有smax[lr]本身有值的时候,再赋予smax[lc]值时会产生覆盖,造成错误;

参考修改代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int maxn=222222;ll minv[maxn*8],maxv[maxn*8],num[maxn*8],addv[maxn*8];int n,p;ll _maxv,_minv;void maintain(int o,int l,int r){    int lc=o<<1,rc=o<<1|1;    if(l==r)        return ;    minv[o]=min(minv[lc],minv[rc]);    maxv[o]=max(maxv[lc],maxv[rc]);}void build(int o,int l,int r){    int lc=o<<1,rc=o<<1|1;    if(l==r)    {        minv[o]=maxv[o]=num[l];        return ;    }    int m=(l+r)>>1;    build(lc,l,m);    build(rc,m+1,r);    maintain(o,l,r);}void pushdown(int o,int l,int r){    int lc=o<<1,rc=lc+1;    if(addv[o])    {        minv[lc]+=addv[o];        minv[rc]+=addv[o];        addv[lc]+=addv[o];        addv[rc]+=addv[o];        maxv[lc]+=addv[o];        maxv[rc]+=addv[o];        addv[o]=0;    }    minv[lc]=max(minv[o],minv[lc]);minv[lc]=min(maxv[o],minv[lc]);    maxv[lc]=min(maxv[o],maxv[lc]);maxv[lc]=max(minv[o],maxv[lc]);    maxv[rc]=min(maxv[o],maxv[rc]);maxv[rc]=max(minv[o],maxv[rc]);    minv[rc]=max(minv[o],minv[rc]);minv[rc]=min(maxv[o],minv[rc]);}void unreduce(int o,int l,int r,int L,int R,ll c){    int m=(l+r)>>1;    int lc=o<<1,rc=o<<1|1;    if(l>=L&&r<=R)    {        maxv[o]=max(maxv[o],c);        minv[o]=max(minv[o],c);        return ;    }    pushdown(o,l,r);    if(L<=m)        unreduce(lc,l,m,L,R,c);    if(R>m)        unreduce(rc,m+1,r,L,R,c);    maintain(o,l,r);}void reduce(int o,int l,int r,int L,int R,ll c){    int m=(l+r)>>1;    int lc=o<<1,rc=o<<1|1;    if(l>=L&&r<=R)    {        minv[o]=min(minv[o],c);        maxv[o]=min(maxv[o],c);        return ;    }    pushdown(o,l,r);    if(L<=m)        reduce(lc,l,m,L,R,c);    if(R>m)        reduce(rc,m+1,r,L,R,c);    maintain(o,l,r);}void add(int o,int l,int r,int L,int R,ll c){    int m=(l+r)>>1;    int lc=o<<1,rc=o<<1|1;    if(l>=L&&r<=R)    {        addv[o]+=c;        minv[o]+=c;        maxv[o]+=c;        return ;    }    pushdown(o,l,r);    if(L<=m)        add(lc,l,m,L,R,c);    if(R>m)        add(rc,m+1,r,L,R,c);    maintain(o,l,r);}void query(int o,int l,int r,int L,int R){    int m=(l+r)>>1;    int lc=o<<1,rc=o<<1|1;    if(l>=L&&r<=R)    {        _minv=min(_minv,minv[o]);        _maxv=max(_maxv,maxv[o]);        return ;    }    pushdown(o,l,r);    if(L<=m)        query(lc,l,m,L,R);    if(R>m)        query(rc,m+1,r,L,R);    maintain(o,l,r);}int main(){    int T;    while(scanf("%d",&T)!=EOF)    while(T--)    {        memset(addv,0,sizeof(addv));        scanf("%d%d",&n,&p);        for(int i=1;i<=n;i++)        {             scanf("%I64d",&num[i]);        }        build(1,1,n);        int l,r;        ll c;        for(int i=0;i<p;i++)        {            int t;            scanf("%d%d%d",&t,&l,&r);            if(t==4)            {                _minv=1e12+7;                _maxv=-1e12+7;                query(1,1,n,l,r);                printf("%I64d %I64d\n",_minv,_maxv);                continue;            }            scanf("%I64d",&c);            if(t==1)            {                add(1,1,n,l,r,c);            }            if(t==2)            {                reduce(1,1,n,l,r,c);            }            if(t==3)            {               unreduce(1,1,n,l,r,c);            }        }    }dai    return 0;}


1 0
原创粉丝点击