UVa 11992 Fast Matrix Operations

这道题要求同时实现快速_求区间最小值,最大值,区间和,区间成段修改,区间成段增减的线段树。
我把刘汝佳的风格和not only but successful 线段树结合在一起搭了一个模板,原理还没理解 。。 刘汝佳的query查询方式+ not only sucess的build 建树。

#include<stdio.h>
#include<algorithm>
#include<string.h>
typedef long long ll;
using namespace std ;
const int INF=1000000002;
const int inf=-INF;
const int  maxnode=1000001<<2;
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
  /* 符号说明*/
 int L,R; 
  /*
    查询区间和修改区间表示为[l ,R] <--声明为全局变量
  */
int _min,_max,_sum;  /*查询区间最小值,最大值,和 */ 
int v; /* Update 的改变量 区间增加 v,区间改成 v */ 
int n,m,op,num;
struct setree{
int  sumv[maxnode],addv[maxnode],minv[maxnode],maxv[maxnode], setv[maxnode];
void PushUp(int rt,int l,int r){ 
    //sumv[rt]=minv[rt]=maxv[rt]=0;
    if(r>l){
        sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1];
        maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
        minv[rt]=min(minv[rt<<1],minv[rt<<1|1]);
    }
    if(setv[rt]>=0){
     minv[rt]=maxv[rt]=setv[rt] ; sumv[rt]=(r-l+1)*setv[rt];
    }
     if(addv[rt]){
        sumv[rt]+=addv[rt]*(r-l+1);
        minv[rt]+=addv[rt];
        maxv[rt]+=addv[rt];
    }
}
  void PushDown(int rt){

      if(setv[rt]>=0){
        setv[rt<<1]=setv[rt<<1|1]=setv[rt];
        addv[rt<<1]=addv[rt<<1|1]=0;
        setv[rt]=-1;
        }
        if(addv[rt]){
        addv[rt<<1]+=addv[rt];
        addv[rt<<1|1]+=addv[rt];
        addv[rt]=0;
        }
  }

void build(int rt,int l,int r){
    addv[rt]=0;
    //  注意 setv[1]=0; 
    if(l==r) {scanf("%I64d",&sumv[rt]);
              addv[rt]=minv[rt]=maxv[rt]=sumv[rt];
              return ;
    }
    int m=l+(r-l)/2;
    build(lson);
    build(rson);
    sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1];
}

 void update(int rt,int l,int r){
   if(L<=l&&r<=R){
       if(op==1) addv[rt]+=v;
       else{
         setv[rt]=v; addv[rt]=0;
       }
   }else{
      PushDown(rt);
   int m=l+(r-l)/2; // m==(R+L)>>1;
   if(L<=m) update(lson);
   else PushUp(lson);
   if(m<R)  update(rson);
   else PushUp(rson);
   }
   PushUp(rt,l,r);
}

 void query(int rt,int l,int r,int add){
    if(setv[rt]>=0){
        int v=setv[rt]+add+addv[rt];
        _sum +=v*(min(R,r)-max(l,L)+1);
        _min =min(_min,v);
        _max =max(_max,v);
    }else if(L<=l&&r<=R){
    _sum+=sumv[rt]+add*(r-l+1);
    _min =min(_min,minv[rt]+add);
    _max =max(_max,maxv[rt]+add);
   }else {
    int m=l+(r-l)/2;
    if(L<=m) query(lson,add+addv[rt]);
    if(m<R)  query(rson,add+addv[rt]);
   }
}
}t[21];
int cnt=0;
int main(){
    void debug();
   //freopen("F:\\123.txt","r",stdin);

   while(scanf("%d%d%d",&n,&m,&num)!=EOF){
       int x1,x2,y1,y2;
       for(int i=1;i<=n;i++){
        memset(t[i].sumv ,0,sizeof(t[i].sumv ));
        memset(t[i].maxv ,0,sizeof(t[i].maxv ));
        memset(t[i].minv ,0,sizeof(t[i].minv ));
        memset(t[i].addv, 0,sizeof(t[i].addv ));
        memset(t[i].setv ,-1,sizeof(t[i].setv ));
        t[i].setv[1]=0;
        }

        for(int i=0;i<num;i++){         
        //debug();  
             scanf("%d%d%d%d%d",&op,&x1,&L,&x2,&R);
              if(op==1||op==2){
                 scanf("%d",&v);
                 for(int i=x1;i<=x2;i++){
                 t[i].update(1,1,m);
               } 
             }else if(op==3){
                  _sum=0; _max=inf; _min=INF;
                  for(int i=x1;i<=x2;i++){
                      t[i].query(1,1,m,0);
                  }
                  printf("%d %d %d\n",_sum,_min,_max);
             }else{

             }
        }
   }
    return 0;
 }

void debug(){
            printf(" %d------------\n",cnt++);
              for(int xx1=1;xx1<=4;xx1++){
                 for(int yy1=1;yy1<=4;yy1++){
                  _sum=0;
                   L=yy1,R=yy1;
                  t[xx1].query(1,1,m,0);
                  printf("%d ",_sum);   
                   }
                   printf("\n");
              } 
             printf("--------------\n");    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值