uva11992

第一次做uva上的题目, 感觉题目的综合性还是蛮好的, 以后应该多做做uva上的题目,要考虑的东西挺多的


快速矩阵变换, 支持3个操作

1  将所给区间内的每个数加上v;

2 将所给区间内的每个数更新为v;

3 求所给区间的和, 最小值, 最大值


需要两个延迟标记 addv[o], setv[o]

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1000005<<2;
const int inf = 1000005;
int sum[maxn], minv[maxn], maxv[maxn];
int addv[maxn], setv[maxn];
int r, c, q, ql, qr, v;
int t, x1, y1, x2, y2;
int n, ans1, ans2, ans3;
void construct(int o, int l, int r)
{
  sum[o] = minv[o] = maxv[o] = 0;
  addv[o] = setv[o] = 0;
  if(l != r)
  	 {
  	 	int m = (l+r) >> 1;
  	 	construct(2*o, l, m);
  	 	construct(2*o+1, m+1, r);
  	 }
}
void pushup(int o)
{
  sum[o] = sum[2*o] + sum[2*o+1];
  minv[o] = min(minv[2*o], minv[2*o+1]);
  maxv[o] = max(maxv[2*o], maxv[2*o+1]);
}
void pushdown(int o, int l, int r)
{
  if(setv[o])
  	 {
  	   setv[2*o] = setv[2*o+1] = setv[o];
  	   addv[2*o] = addv[2*o+1] = 0;         // 之前就是少了这一步, 一直没过
  	   int m = (l+r) >> 1;
  	   sum[2*o] = setv[o] * (m-l+1);
  	   sum[2*o+1] = setv[o] * (r-m);
  	   minv[2*o] = minv[2*o+1] = setv[o];
  	   maxv[2*o] = maxv[2*o+1] = setv[o];
  	   setv[o] = 0; 
  	 }
  if(addv[o])
    {
      addv[2*o] += addv[o];
      addv[2*o+1] += addv[o];
      int m = (l+r) >> 1;
      sum[2*o] += (m-l+1) * addv[o];
      sum[2*o+1] += (r-m) * addv[o];
      minv[2*o] += addv[o];
      maxv[2*o] += addv[o];
      minv[2*o+1] += addv[o];
      maxv[2*o+1] += addv[o];
      addv[o] = 0;
    }
}
void add(int o, int l, int r)
{
  if(ql<=l && qr>=r)
    {
      addv[o] += v;
      sum[o] += (r-l+1) * v;
      minv[o] += v;
      maxv[o] += v;
      return;
    }
   pushdown(o,  l, r);
   int m = (l+r) >> 1;
   if(ql <= m)
   	 add(2*o,  l, m);
   if(qr > m)
     add(2*o+1, m+1, r);
   pushup(o);
}
void set(int o, int l, int r)
{
  if(ql<=l && qr>=r)
    {
      setv[o] = v;
      sum[o] = v*(r-l+1);
      minv[o] = maxv[o] = v;
      addv[o] = 0;
      return;
    }
   pushdown(o,  l, r);
   int m = (l+r) >> 1;
   if(ql <= m)
   	 set(2*o, l, m);
   if(qr > m)
     set(2*o+1, m+1, r);
   pushup(o);
}
void query(int o, int l, int r)
{
  if(ql<=l && qr>=r)
    {
      ans1 += sum[o];
      ans2 = min(ans2, minv[o]);
      ans3 = max(ans3, maxv[o]);
      return;
    }
  pushdown(o,  l, r);
  int m = (l+r) >> 1;
  if(ql <= m)
  	query(2*o, l, m);
  if(qr > m)
  	query(2*o+1, m+1, r);
}
int main()
{
  while(scanf("%d %d %d", &r, &c, &q) == 3)
  	 {
  	 	n = r*c;
  	 	construct(1, 1, n);
  	 	while(q--)
  	 	  {
  	 	  	 scanf("%d %d %d %d %d", &t, &x1, &y1, &x2, &y2);
  	 	  	 if(t == 1)
  	 	  	   {
  	 	  	   	 scanf("%d", &v);
  	 	  	   	 for(int i=x1; i<=x2; i++)
  	 	  	   	   {
  	 	  	   	   	  ql = (i-1)*c + y1;
  	 	  	   	   	  qr = (i-1)*c + y2;
  	 	  	   	   	  add(1, 1, n);
  	 	  	   	   }
  	 	  	   }
  	 	  	 if(t == 2)
  	 	  	  {
  	 	  	  	 scanf("%d", &v);
  	 	  	  	 for(int i=x1;  i<=x2; i++)
  	 	  	  	   {
  	 	  	  	   	 ql = (i-1)*c + y1;
  	 	  	  	   	 qr = (i-1)*c + y2;
  	 	  	  	   	 set(1, 1, n);
  	 	  	  	   }
  	 	  	  }
  	 	  	if(t == 3)
  	 	  	  {
  	 	  	     ans1 = 0;
  	 	  	     ans2 = inf;
  	 	  	     ans3 = -inf;
  	 	  	     for(int i=x1;  i<=x2; i++)
  	 	  	       {
  	 	  	       	 ql = (i-1)*c + y1;
  	 	  	       	 qr = (i-1)*c + y2;
  	 	  	       	 query(1, 1, n);
  	 	  	       }
  	 	  	     printf("%d %d %d\n", ans1, ans2, ans3);
  	 	  	  }
  	 	  }
  	 }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值