• uva 11992


    题意:

    给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作。

    1 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素add上val;

    2 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素set为val;

    3 x1 y1 x2 y2 val 表示输出(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素的sum,最大最小值

    链接:

    https://vjudge.net/contest/203644#problem/B

    题解:

    显然这两个操作是可以用线段树来维护的,但关键在于二维

    注意到n<=20 ,所以可以考虑对每一行对列进行线段树维护

    另外修改为v和增加v两个操作的同时存在

    要注意:修改为v要清空增加v 并且先处理修改为v后处理增加v

    代码:

    #include <bits/stdc++.h>
    #define mid (h+t)/2
    using namespace std;
    struct re{int a,b,c;} tmp;
    struct ree{int h,t,x1,x2,x3,lazy1,lazy2;}p[22][300000];
    void build(int hh,int x,int h,int t)
    {  
      p[hh][x].h=h; p[hh][x].t=t; p[hh][x].x3=0;
      if (h==t) 
        {
            return;
      }
      build(hh,x*2,h,mid); build(hh,x*2+1,mid+1,t);
    };
    void down(int hh,int x)
    {
        if (p[hh][x].lazy2!=0) 
        {
          p[hh][x].x1=(p[hh][x].t-p[hh][x].h+1)*p[hh][x].lazy2;
          p[hh][x].x2=p[hh][x].lazy2;
          p[hh][x].x3=p[hh][x].lazy2;
          p[hh][x*2].lazy2=p[hh][x].lazy2;
          p[hh][x*2+1].lazy2=p[hh][x].lazy2;
          p[hh][x*2].lazy1=p[hh][x*2+1].lazy1=0; 
          p[hh][x].lazy2=0;
      }
      p[hh][x].x1+=(p[hh][x].t-p[hh][x].h+1)*p[hh][x].lazy1;
      p[hh][x].x2+=p[hh][x].lazy1;
      p[hh][x].x3+=p[hh][x].lazy1;
      p[hh][x*2].lazy1+=p[hh][x].lazy1;
      p[hh][x*2+1].lazy1+=p[hh][x].lazy1;
      p[hh][x].lazy1=0;
    }; 
    void change1(int hh,int x,int sum,int h,int t)
    {
        down(hh,x); 
        if (h>p[hh][x].t || p[hh][x].h>t) return;
        if (h<=p[hh][x].h && p[hh][x].t<=t)
        {
          p[hh][x].lazy1+=sum,down(hh,x);
            return;
      }
        change1(hh,x*2,sum,h,t);
        change1(hh,x*2+1,sum,h,t);
        p[hh][x].x1=p[hh][x*2].x1+p[hh][x*2+1].x1;
      p[hh][x].x2=max(p[hh][x*2].x2,p[hh][x*2+1].x2);
      p[hh][x].x3=min(p[hh][x*2].x3,p[hh][x*2+1].x3);
    };
    void change2(int hh,int x,int sum,int h,int t)
    {
        down(hh,x);
        if (h>p[hh][x].t || p[hh][x].h>t) return;
        if (h<=p[hh][x].h && p[hh][x].t<=t)
        {
          p[hh][x].lazy1=0,p[hh][x].lazy2=sum,down(hh,x);
            return;
      }
        change2(hh,x*2,sum,h,t);
        change2(hh,x*2+1,sum,h,t);
        p[hh][x].x1=p[hh][x*2].x1+p[hh][x*2+1].x1;
      p[hh][x].x2=max(p[hh][x*2].x2,p[hh][x*2+1].x2);
      p[hh][x].x3=min(p[hh][x*2].x3,p[hh][x*2+1].x3);
    };
    re query(int hh,int x,int h,int t)
    {  
      re tmp,tmp1,tmp2;
      tmp.a=0; tmp.b=0; tmp.c=1000000000;
      down(hh,x);
        if (h>p[hh][x].t || p[hh][x].h>t) return(tmp);
        if (h<=p[hh][x].h && p[hh][x].t<=t)
        {
            tmp.a=p[hh][x].x1,tmp.b=p[hh][x].x2,tmp.c=p[hh][x].x3;
            return(tmp);
      }
        tmp1=query(hh,x*2,h,t); tmp2=query(hh,x*2+1,h,t);
        tmp.a=tmp1.a+tmp2.a; tmp.b=max(tmp1.b,tmp2.b); tmp.c=min(tmp1.c,tmp2.c);
        return(tmp);
    };
    int main()
    {
      int n,m,k,a1,a2,a3,a4,a5,a6;
      while (cin>>n>>m>>k)
      {
          memset(p,0,sizeof(p));
          for (int i=1; i<=n;i++)
            build(i,1,1,m);
          for (int i=1;i<=k;i++)
        {
            cin>>a1>>a2>>a3>>a4>>a5;
            if (a1==1)
            {
                cin>>a6;
                for (int j=a2;j<=a4;j++)
                  change1(j,1,a6,a3,a5);
            }
            if (a1==2)
            {
                cin>>a6;
                for (int j=a2;j<=a4;j++)
                  change2(j,1,a6,a3,a5);
            }
            if (a1==3)
            {
                int sum1=0,maxn=0,minn=1000000000; 
                for (int j=a2;j<=a4;j++)
                    {
                        tmp=query(j,1,a3,a5);
                        sum1+=tmp.a;
                        maxn=max(maxn,tmp.b);
                        minn=min(minn,tmp.c);
                  }
                  cout<<sum1<<" "<<minn<<" "<<maxn<<endl; 
            }
        }
      }
      return(0);
    }
  • 相关阅读:
    linux网络编程 inet_aton(); inet_aton; inet_addr;
    linux网络编程 ntohs, ntohl, htons,htonl inet_aton等详解
    linux C++ scandir 的使用
    linux 多线程编程-读写者问题
    为什么修改头文件make不重新编译
    syslog(),closelog()与openlog()--日志操作函数
    VC:CString用法整理(转载)
    VC6.0实用小技巧
    HTml js 生成图片
    C++中两个类相互包含引用问题
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8067997.html
Copyright © 2020-2023  润新知