Fast Matrix Operations UVA - 11992

文章目录


原版刘汝佳的代码有很多maintain语句,个人感觉这样很不符合习惯,所以做出了修改,更符合我的习惯

1: 只保留一个update时的maintain语句
2:时刻记着延迟标记只是延迟往下的标记,并不延迟节点本身,时刻修改,当延迟标记下到某个地方,它的值就应该被修改

// UVa11992 Fast Matrix Operations(更易读、更具一般性的版本)
// Rujia Liu
// 注意:所有叶子上总是保留set标记而不会被清除(pushdown只能针对非叶结点),因此maintain函数对于叶子来说并不会重复累加addv[o]
// 本程序在query的时候进行了标记传递(即pushdown),更具一般性,代码可读性也更强,但执行效率较低
// 有兴趣的读者请参考代码仓库中的uva11992.cpp,那个写法是书上例题中的代码,避开了query中的标记传递,执行效率比本代码高

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxnode = 1<<17;
const int INF = 1000000000;

int op, x1, x2, y1, y2, x, v;

struct IntervalTree {
  int sumv[maxnode], minv[maxnode], maxv[maxnode], setv[maxnode], addv[maxnode];

  // 维护信息
  void maintain(int o, int L, int R) {
    int lc = o*2, rc = o*2+1;
    if(R > L) {
      sumv[o] = sumv[lc] + sumv[rc];
      minv[o] = min(minv[lc], minv[rc]);
      maxv[o] = max(maxv[lc], maxv[rc]);
    }
    if(setv[o] >= 0) { minv[o] = maxv[o] = setv[o]; sumv[o] = setv[o] * (R-L+1); }
    if(addv[o]) { minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += addv[o] * (R-L+1); }
  }

  // 标记传递
  void pushdown(int o,int l,int r) {
    int lc = o*2, rc = o*2+1;
    int m = (l+r)>>1;
    if(setv[o] >= 0) {
      setv[lc] = setv[rc] = setv[o];
      sumv[lc] = setv[o]*(m-l+1);
      sumv[rc] = setv[o]*(r-m);
      minv[lc] = minv[rc] = setv[o];
      maxv[lc] = maxv[rc] = setv[o];
      addv[lc] = addv[rc] = 0;
      setv[o] = -1; // 清除本结点标记
    }
    if(addv[o]) {
      sumv[lc] += addv[o]*(m-l+1);
      sumv[rc] += addv[o]*(r-m);
      minv[lc] += addv[o];
      maxv[lc] += addv[o];
      minv[rc] += addv[o];
      maxv[rc] += addv[o];
      addv[lc] += addv[o];
      addv[rc] += addv[o];
      addv[o] = 0; // 清除本结点标记
    }
  }

  void update(int o, int L, int R) {
    int lc = o*2, rc = o*2+1;
    if(y1 <= L && y2 >= R) { // 标记修改 
      if(op == 1) {
        addv[o] += v;
        sumv[o] += (R-L+1)*v;
        maxv[o] += v;
        minv[o] += v;
      }
      else {
        setv[o] = v; addv[o] = 0; 
        sumv[o] = (R-L+1)*v;
        maxv[o] = v;
        minv[o] = v;
      }
    } else {
      pushdown(o,L,R);
      int M = L + (R-L)/2;
      if(y1 <= M) update(lc, L, M);//else maintain(lc, L, M);
      if(y2 > M) update(rc, M+1, R);// else maintain(rc, M+1, R);
       maintain(o, L, R);
    }
   
  }

  void query(int o, int L, int R, int& ssum, int& smin, int &smax) {
    int lc = o*2, rc = o*2+1;
     //maintain(o, L, R); // 处理被pushdown下来的标记
    if(y1 <= L && y2 >= R) {
      ssum = sumv[o];
      smin = minv[o];
      smax = maxv[o];
    } else {
      pushdown(o,L,R);
      int M = L + (R-L)/2;
      int lsum = 0, lmin = INF, lmax = -INF;
      int rsum = 0, rmin = INF, rmax = -INF;
      if(y1 <= M) query(lc, L, M, lsum, lmin, lmax); //else maintain(lc, L, M);
      if(y2 > M) query(rc, M+1, R, rsum, rmin, rmax); //else maintain(rc, M+1, R);
      ssum = lsum + rsum;
      smin = min(lmin, rmin);
      smax = max(lmax, rmax);
    }
  }

};

const int maxr = 20 + 5;

IntervalTree tree[maxr];

int main() {
  int r, c, m;
  while(scanf("%d%d%d", &r, &c, &m) == 3) {
    memset(tree, 0, sizeof(tree));
    for(x = 1; x <= r; x++) {
      memset(tree[x].setv, -1, sizeof(tree[x].setv));
      tree[x].setv[1] = 0;
    }
    while(m--) {
      scanf("%d%d%d%d%d", &op, &x1, &y1, &x2, &y2);
      if(op < 3) {
        scanf("%d", &v);
        for(x = x1; x <= x2; x++) tree[x].update(1, 1, c);
      } else {
        int gsum = 0, gmin = INF, gmax = -INF;
        for(x = x1; x <= x2; x++) {
          int ssum, smin, smax;
          tree[x].query(1, 1, c, ssum, smin, smax);
          gsum += ssum; gmin = min(gmin, smin); gmax = max(gmax, smax);
        }
        printf("%d %d %d\n", gsum, gmin, gmax);
      }
    }
  }
  return 0;
}

全部评论

相关推荐

头像
05-16 12:47
已编辑
中国地质大学(武汉) Java
你出生在农村,与其它农村小孩子无异小学时你对成绩没有概念,只感觉上课不听课也是无聊,只知道不写完作业会被老师罚站一到考试,自己成绩总是名列靠前,即使偶尔落后,你也从不在意中学时你觉得课本的东西很简单,随便学学就会了,并没有大量刷题你总是想不通,那些所谓的数学物理中难题,明明是在送分,为什么你的同学总是想不出解题方法高中时这三年你过的不容易,晚睡早起,给了自己很多压力.但是你也发现自己是有些小聪明的,你感觉班里有些同学很刻苦,但成绩比你差远了。那些数学题和物理题的陷阱,同学一遍遍踩坑,但是你总能发现并避开它们.“为了父母的期盼,为了恩师的厚望,为了天赐的智慧,为了青春的理想......”“天行健...
创作助手_刘北:其实,这种已经是神童级别的了,不费吹灰之力就能拿到自己想要的东西,就像机器按照程序走了一遍,就像我小时候看爱情公寓,觉得他们都很惨,几个人只能挤在一个房间里合租,但是好在他们有一群非常好的朋友,随着时间的推移,慢慢长大了,在看爱情公寓的时候,觉得他们都很厉害,博士、留学生、***、电台公子,数学天才,任何一个都是我可望而不可即的,更别说可以在异地认识一群更好的朋友了,所以呢,人还是要自给自足,满足当下,不要攀比,意气风发的且有理想的18岁少年永远都存在,只不过随着时间的推移他被你包裹在了洋葱的最深处。
点赞 评论 收藏
分享
小厂面经,也是我的处女面(30min)1.自我介绍2.spring&nbsp;boot的自动装配原理(好多类和接口的单词都忘了全称是啥了,就说了记得的单词,流程应该说对了吧)3.有用过redis吗?主要是用在实现什么功能(说了技术派用redis的zset来实现排行榜)5.有了解过Redisson吗?讲一下对于分布式锁的了解以及在什么场景下应用(说了秒杀场景)6.对mysql有了解吗?包括它的索引优化和创建(把想起来的全说了)7.了解设计模式吗?比如单例模式,为什么要使用单例模式,它的优点是什么(昨天刚看的设计模式)8.工厂模式有了解吗?主要的使用场景是?(也是昨天刚看的)9.场景题:有7个服务器,需要在早上十点定时的向数据库中的用户表中的用户发短信,如果做到发送的消息不重复,且如果发送失败了需要知道是到哪个用户失败了,这样下次就直接从这个用户开始(我答了用spring&nbsp;task来实现定时,用分布式锁来保证只有一份服务器可以发送消息,用消息队列来存储消息,然后用消息确认机制来保证错误信息的记录,以及在数据库或者业务层面完成消息消费的幂等性)10.场景题:如果在系统启动的时间就将数据库的所有用户相关的信息都读到一个hashmap中(这个没啥思路,没答好)27届的投了一个星期终于有一个面试了,大部分公司都只招26的
inari233:已oc,拒了
查看9道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务