UVa 11992 add与set结合区间修改线段树

来源:互联网 发布:寄生虫推广软件 编辑:程序博客网 时间:2024/05/16 12:23

差点忘记还有这么一个线段树的题目,白书上的最后一个例题了,也是足见其难度啊,和一般的题目就是不一样,这个需要考虑的是set和add两种情况同时存在的情况了,这个需要考虑的就是当add先在某一段区间标记了,那么如果下一次当该区间又标记了set的话,实际上前面做到add就没用了,可以直接被抹去了,而如果在set之后又来了一次的set的话,那样的话两者都需要保留下来,那么难点就来了,在pushdown这里的话,肯定需要先判读set标记了,如果set存在的话那么对其左右子树进行各种操作了,特别的需要对左右子节点的add标志要清零,因为下面对左右子节点的set要进行操作了那就和前面说道的一样,set出现,那么之前的add都不算数了,其他的各种指标只要合理操作即可了。

这题还是有点难度的,参考了这篇博文:http://blog.csdn.net/a601025382s/article/details/38356535

还有就是我的这里的代码的写法不如上面博客的,因为写惯了不是结构体的写法,在这个多指标的情况下,其实还是一开始就直接写结构体会来的更加方便一些。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l, m, rt<<1#define rson m+1, r, rt<<1|1#define mid int m = (l + r)>>1const int maxn=10e6+5;int r,c,m,tag,x1,x2,y1,y2,v;int adds[maxn<<2],sets[maxn<<2],sum[maxn<<2],maxs[maxn<<2],mins[maxn<<2];struct node{    int sum,maxs,mins;};void build(int l,int r,int rt){    adds[rt]=sets[rt]=sum[rt]=maxs[rt]=mins[rt]=0;    if(l==r)        return ;    mid;    build(lson);    build(rson);}void pushdown(int l,int r,int rt){    if(sets[rt]!=0)//当有两个标记时,必定是add要在set之后做的    {      adds[rt*2]=adds[rt*2+1]=0;      sets[rt*2]=sets[rt*2+1]=sets[rt];      mins[rt*2]=mins[rt*2+1]=maxs[rt*2]=maxs[rt*2+1]=sets[rt];       mid;      sum[rt*2]=(m-l+1)*sets[rt];      sum[rt*2+1]=(r-m)*sets[rt];      sets[rt]=0;    }    if(adds[rt]!=0)    {        adds[rt*2]+=adds[rt];        adds[rt*2+1]+=adds[rt];        maxs[rt*2]+=adds[rt];        maxs[rt*2+1]+=adds[rt];        mins[rt*2]+=adds[rt];        mins[rt*2+1]+=adds[rt];        mid;        sum[rt*2]+=(m-l+1)*adds[rt];        sum[rt*2+1]+=(r-m)*adds[rt];        adds[rt]=0;    }}void update_add(int l,int r,int rt,int x,int y,int z){    if(x<=l&&y>=r)    {        adds[rt]+=z;        maxs[rt]+=z;        mins[rt]+=z;        sum[rt]+=(r-l+1)*z;        return ;    }    mid;    pushdown(l,r,rt);    if(x<=m) update_add(lson,x,y,z);    if(y>m) update_add(rson,x,y,z);    maxs[rt]=max(maxs[rt*2],maxs[rt*2+1]);    mins[rt]=min(mins[rt*2],mins[rt*2+1]);    sum[rt]=sum[rt*2]+sum[rt*2+1];}void update_set(int l,int r,int rt,int x,int y,int z){    if(x<=l&&y>=r)    {        adds[rt]=0;//因为置位set的优先级肯定要高啊,因为不管先前add了多少的值在这段区间,如果只要出现了一次的set那么值都是set放的z值        sets[rt]=z;        maxs[rt]=z;        mins[rt]=z;        sum[rt]=(r-l+1)*z;        return ;    }    pushdown(l,r,rt);    mid;    if(x<=m) update_set(lson,x,y,z);    if(y>m) update_set(rson,x,y,z);    maxs[rt]=max(maxs[rt*2],maxs[rt*2+1]);    mins[rt]=min(mins[rt*2],mins[rt*2+1]);    sum[rt]=sum[rt*2]+sum[rt*2+1];}node query(int l,int r,int rt,int x,int y){    if(x<=l&&y>=r)    {        node tmp;        tmp.maxs=maxs[rt];        tmp.mins=mins[rt];        tmp.sum=sum[rt];        return tmp;    }    pushdown(l,r,rt);    mid;    node t;    if(y<=m) return query(lson,x,y);    else if(x>m) return query(rson,x,y);    else    {      node p,q;      p=query(lson,x,y);      q=query(rson,x,y);      t.sum=p.sum+q.sum;      t.maxs=max(p.maxs,q.maxs);      t.mins=min(p.mins,q.mins);        return t;    }}int main(){    while(scanf("%d%d%d",&r,&c,&m)!=EOF)    {        build(1,r*c,1);     while(m--)     {         scanf("%d%d%d%d%d",&tag,&x1,&y1,&x2,&y2);         if(tag==3)         {             node ans,p;            for(int i=x1;i<=x2;i++)            {                if(i==x1)                    ans=query(1,r*c,1,(i-1)*c+y1,(i-1)*c+y2);                else                {                    p=query(1,r*c,1,(i-1)*c+y1,(i-1)*c+y2);                    ans.sum+=p.sum;                    ans.maxs=max(ans.maxs,p.maxs);                    ans.mins=min(ans.mins,p.mins);                }            }            printf("%d %d %d\n",ans.sum,ans.mins,ans.maxs);         }         else if(tag==2)         {          scanf("%d",&v);          for(int i=x1;i<=x2;i++)          update_set(1,r*c,1,(i-1)*c+y1,(i-1)*c+y2,v);         }         else if(tag==1)         {          scanf("%d",&v);          for(int i=x1;i<=x2;i++)          update_add(1,r*c,1,(i-1)*c+y1,(i-1)*c+y2,v);         }     }    }    return 0;}






0 0
原创粉丝点击