UVa 11992 Fast Matrix Operations(两种标记的线段树)

来源:互联网 发布:c语言|是什么 编辑:程序博客网 时间:2024/05/16 17:35
本题涉及到了线段数大多数基本操作。
因为只有20行,所以可以建20个线段树。
线段树最重要的两个函数:
pushdown 下移标记,并更新子节点数据。
pushup  由2个子节点数据更新父节点数据。


写法有很多,介绍一种不容易错的:
保证在设置标记的同时更新节点信息。即:在update给某节点打标记,以及pushdown下发标记时,都马上更新节点信息。
这样写的效果是pushup很短,直接更新,因为子节点的信息已经保证被更新过了,不需要考虑标记。相反在pushdown的时候要写很长,因为要直接更新子节点。


set操作会清空add标记。


代码:

////  main.cpp//  11992 Fast Matrix Operations////  Created by Baoli1100 on 15/3/14.//  Copyright (c) 2015年 Baoli1100. All rights reserved.//#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define maxn 800005#define INF 1000000000struct Tree{    int Sum[maxn],Min[maxn],Max[maxn],add[maxn],Set[maxn];    int sumr,minr,maxr;    int op,y1,y2;    void init(){        memset(Sum,0,sizeof(Sum));        memset(add,0,sizeof(add));        memset(Set,-1,sizeof(Set));        memset(Min,0,sizeof(Min));        memset(Max,0,sizeof(Max));    };    void pushup(int rt){        int lc=rt<<1,rc=rt<<1|1;        Sum[rt]=Sum[lc]+Sum[rc];        Min[rt]=min(Min[lc],Min[rc]);        Max[rt]=max(Max[lc],Max[rc]);    }    void pushdown(int rt,int L,int R){        int lc=rt<<1,rc=rt<<1|1;        int M=(L+R)/2;        if(Set[rt]>=0){            Set[lc]=Set[rc]=Set[rt];            add[lc]=add[rc]=0;            Max[lc]=Max[rc]=Min[lc]=Min[rc]=Set[rt];            Sum[lc]=(M-L+1)*Set[rt];            Sum[rc]=(R-M)*Set[rt];            Set[rt]=-1;        }        if(add[rt]){            add[lc]+=add[rt];            add[rc]+=add[rt];            Max[lc]+=add[rt];Min[lc]+=add[rt];            Max[rc]+=add[rt];Min[rc]+=add[rt];            Sum[lc]+=add[rt]*(M-L+1);            Sum[rc]+=add[rt]*(R-M);            add[rt]=0;        }    }    void update(int rt,int L,int R,int v){        int lc=rt<<1,rc=rt<<1|1;        int M=(L+R)/2;        if(y1<=L&&y2>=R){            if(op==1){                add[rt]+=v;                Sum[rt]+=v*(R-L+1);                Max[rt]+=v;                Min[rt]+=v;            }            else {                Set[rt]=v;                add[rt]=0;                Max[rt]=Min[rt]=v;                Sum[rt]=v*(R-L+1);            }        }        else{            pushdown(rt,L,R);            if(y1<=M) update(lc,L,M,v);            if(y2>M) update(rc,M+1,R,v);            pushup(rt);        }    }    void Query(int rt,int L,int R){        int lc=rt<<1,rc=rt<<1|1;        int M=(L+R)/2;        if(y1<=L&&y2>=R){            sumr+=Sum[rt];            maxr=max(maxr,Max[rt]);            minr=min(minr,Min[rt]);            return;        }        else {            pushdown(rt,L,R);            if(y1<=M){                Query(lc,L,M);            }            if(y2>M) Query(rc,M+1,R);            pushup(rt);        }    }}T[25];int R,C,M;int main(){    while(~scanf("%d%d%d",&R,&C,&M)){        for(int i=1;i<=R;i++){            T[i].init();        }        int op,x1,x2,y1,y2,v;        for(int i=1;i<=M;i++){            scanf("%d",&op);            if(op<3){                scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&v);                for(int i=x1;i<=x2;i++){                    T[i].y1=y1;T[i].y2=y2;T[i].op=op;                    T[i].update(1,1,C,v);                }            }            else{                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);                int rmin=INF,rmax=-INF,rsum=0;                for(int i=x1;i<=x2;i++){                    T[i].minr=INF;T[i].maxr=-INF;T[i].sumr=0;                    T[i].y1=y1;T[i].y2=y2;                    T[i].Query(1,1,C);                    rmin=min(rmin,T[i].minr);                    rmax=max(rmax,T[i].maxr);                    rsum+=T[i].sumr;                }                printf("%d %d %d\n",rsum,rmin,rmax);            }        }    }    return 0;}/* 3 3 111 1 1 1 1 1 1 3 1 1 1 1 2 1 1 2 2 0 3 1 1 1 1 */


0 0
原创粉丝点击