uva 11992 Fast Matrix Operations(线段树)

模板题:区间更新 、查询.

看似简单,但敲出来漏洞百出。。。 还是对线段树不熟悉。。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 3000000+50 ;   // 要开3倍 ,2被会wa ,很奇怪。
const int INF = 1e9;
#define Lson o<<1 , L , mid
#define Rson o<<1|1, mid+1 , R
#define clr(a , b) memset(a , 0 , (b)*sizeof(a[0]))

struct segment_tree{
  int sum[maxn] , ma[maxn] , mi[maxn] ,st[maxn], add[maxn] ;
  void Build(int n){
    clr(sum , n*3+10),clr(ma , n*3+10),clr(mi , n*3+10),clr(add , n*3+10);
    memset(st , -1, (n*3+10)*sizeof(st[0])) ;
  }
  inline void update(int o){
    int lo = o<<1 , ro = o<<1|1 ;
    sum[o] = sum[lo] + sum[ro] ;
    ma[o] = max(ma[lo] , ma[ro]) ;
    mi[o] = min(mi[lo] , mi[ro]) ;
  }
  inline void pushdown(int o,int L,int R){
    int lo = o<<1 , ro = o<<1|1 ;
    if(st[o] !=-1){
      sum[o] = st[o] * (R-L+1) , ma[o] = st[o] , mi[o] = st[o] ;
      if(L<R) st[lo] = st[ro] = st[o] , add[lo] = add[ro] = 0 ;
      st[o] = -1 ;
    }
    if(add[o]){
      sum[o] += add[o]*(R-L+1) , ma[o]+=add[o] , mi[o] += add[o] ;
      if(L<R) add[lo]+=add[o] , add[ro]+=add[o] ;
      add[o] = 0;
    }
  }

  int sL , sR , sV ;
  void Set(int o ,int L ,int R){
    pushdown(o , L ,R) ;
    int lo = o<<1 , ro = o<<1|1 , mid = (R+L)>>1 ;
    if(sL <=L && R<=sR){
      sum[o] = sV*(R-L+1) , ma[o] = sV , mi[o] = sV ;
      if(L<R) pushdown(Lson) , pushdown(Rson) ,st[lo]=st[ro]=sV , add[lo]=add[ro]=0;
      return ;     // 更新节点信息前一定要先将节点原来的信息传递下去。
    }
    if(sL <= mid) Set(Lson);  else pushdown(Lson) ;
    if(sR > mid) Set(Rson) ;  else pushdown(Rson) ;
    update(o) ;
  }

  int aL , aR , aV ;
  void Add(int o, int L , int R){
    pushdown(o,L,R) ;
    int lo=o<<1 , ro = o<<1|1 , mid = (L+R)>>1 ;
    if(aL <=L && R<= aR){
      sum[o]+=aV*(R-L+1) , ma[o]+=aV , mi[o]+=aV ;
      if(L<R) pushdown(Lson) , pushdown(Rson) ,add[lo]+=aV , add[ro]+=aV;
      return ;   // 同上 ,需要注意!!
    }
    if(aL <= mid) Add(Lson); else pushdown(Lson) ;  // 为使下面update不会出错. 本节点信息正确性依赖于儿子信息.
    if(aR > mid) Add(Rson);  else pushdown(Rson) ;
    update(o) ;
  }

  int qL , qR , q_sum , q_max , q_min ;
  void Query(int o , int L ,int R){
    pushdown(o,L,R);
    int mid = (L+R)>>1 ;
    if(qL<=L && R<=qR) {
      q_sum += sum[o] , q_max = max(q_max , ma[o]) , q_min = min(q_min , mi[o]) ;
      return ;
    }
    if(qL<=mid) Query(Lson);
    if(qR>mid) Query(Rson);
  }
}T[22];

int main()
{
  //freopen("in.txt","r",stdin);
  int r ,n ,m ;
  while(scanf("%d%d%d" , &r ,&n ,&m)==3){
    for(int i=1; i<=r ;i++) T[i].Build(n);
    int op , x1 , x2 , y1 ,y2, v;
    while(m--){
      scanf("%d %d %d %d %d", &op , &x1 ,&y1 , &x2 ,&y2) ;
      if(op==1){
        scanf("%d" , &v) ;
        for(int i=x1; i<=x2; i++){
          T[i].aL = y1 , T[i].aR = y2 ,T[i].aV = v;
          T[i].Add(1,1,n);
        }
      } else if(op==2) {
        scanf("%d" ,&v) ;
        for(int i=x1; i<=x2 ;i++){
          T[i].sL = y1 , T[i].sR = y2 ,T[i].sV = v ;
          T[i].Set(1,1,n);
        }
      } else {
        int ssum = 0 , mmax = -INF , mmin = INF ;
        for(int i=x1; i<=x2; i++){
          T[i].qL = y1 , T[i].qR = y2 , T[i].q_sum =0 , T[i].q_max=-INF , T[i].q_min = INF ;
          T[i].Query(1,1,n);
          ssum+=T[i].q_sum , mmax = max(mmax , T[i].q_max) , mmin = min(mmin , T[i].q_min);
        }
        printf("%d %d %d\n" ,ssum , mmin , mmax) ;
      }
    }
  }
  return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《算法竞赛入门经典——训练指南》代码仓库 例题代码 限于篇幅,书上并没有给出所有例题的代码,这里给出了所有例题的代码,并且改进了书上的一些代码。 第一章 32题 38份代码 第二章 28题 30份代码 第三章 22题 23份代码 第四章 19题 21份代码 第五章 34题 39份代码 第六章 24题 26份代码 共159题 177份代码 为了最大限度保证代码风格的一致性,所有例题代码均由刘汝佳用C++语言编写。 所有代码均通过了UVa/La的测试,但不能保证程序是正确的(比如数据可能不够强),有疑问请致信[email protected],或在googlecode中提出: http://code.google.com/p/aoapc-book/ [最新更新] 2013-04-23 增加字符串中例题10(UVa11992 Fast Matrix Operations)的另一个版本的程序,执行效率较低,但更具一般性,可读性也更好 2013-04-22 增加字符串部分“简易搜索引擎”代码,可提交到UVa10679 2013-04-13 修正Treap中优先级比较的bug(原来的代码实际上是在比较指针的大小!),加入纯名次树代码 2013-03-31 修正UVa1549标程的bug,即buf数组不够大。 增加线段树部分“动态范围最小值”的完整代码 2013-03-23 修正UVa10054标程的bug,即没有判断是否每个点的度数均为偶数。UVa数据已经更新 LA3401修正了代码和文字不一致的问题 UVa11270增加了答案缓存 2013-03-21 增加线段树部分中两个经典问题的完整代码:快速序列操作I和快速序列操作II 2013-02-28 补全所有159道例题的代码

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值