• 20181030noip模拟赛T1


    YY的矩阵

    YY有一个大矩阵(N*M), 矩阵的每个格子里都有一个整数权值W[i,j](1<=i<=M,1<=j<=N)

    对于这个矩阵YY会有P次询问,每次询问这个大矩阵的一个子矩阵内的最大值。

    输入

    第一行两个整数N和M。

    接下来N行,每行M个整数

    然后,一行是整数P;

    接下来P行,每行4个整数r1, c1, r2, c2(分别表示子矩阵的左上角坐标和右下角坐标)

    输出

    共P行,每行一个整数,表示相应的最大值。

    Input

    4 4

    4 4 10 7

    2 13 9 11

    5 7 8 20

    13 20 8 2

    4

    1 1 4 4

    1 1 3 3

    1 3 3 4

    1 1 1 1

    Output

    20

    13

    20

    4

    数据范围:

    60%的数据:N×M×P<10^8

    100%的数据:1 <= N, M <= 300;1 <= P <= 1,000,000;1 <= r1 <= r2 <= N, 1 <= c1 <= c2 <= M,1<=W[i][j]<=10000.

    思路:

    听说正解是二维rmq??

    本人懒得敲……

    于是便有了一个O(n^3+p*n)的算法

    首先O(N^3)预处理出dp[i][j][k]表示第i行从j到k的最大值

    然后对于每组询问

    O(x2-x1)的扫一遍即可

    (跑满好像要300000000,然而我好像是全场跑的最快的????)

    代码:

    #include<iostream>
    #include<cstdio>
    #define rii register int i
    #define rij register int j
    #define rik register int k 
    using namespace std;
    int dt[305][305],m,n,p,dp[305][305][305];
    inline void ycl()
    {
        for(rii=1;i<=n;++i)
        {    
            for(rij=1;j<=m;++j)
            {
                dp[i][j][j]=dt[i][j];
                for(rik=j+1;k<=m;++k)
                {
                    if(dp[i][j][k-1]>dt[i][k])
                    {
                        dp[i][j][k]=dp[i][j][k-1];
                    }
                    else
                    {
                        dp[i][j][k]=dt[i][k];
                    }
                }
            }
        }
    }
    inline int rd(){
        register int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    inline void out(int a)
    {
        if(a<0)
        {
              putchar('-');
              a=-a;
        }
        if(a>9)
        out(a/10);
        putchar(a%10+'0');
    }
    int main()
    {
        freopen("yy.in","r",stdin);
        freopen("yy.out","w",stdout);
        n=rd();
        m=rd();
        for(rii=1;i<=n;++i)
        {
            for(rij=1;j<=m;++j)
            {
                dt[i][j]=rd();
            }
        }
        ycl();
        scanf("%d",&p);
        for(rii=1;i<=p;++i)
        {
            int x1=rd(),y1=rd(),x2=rd(),y2=rd();
            int ans=0;
            for(rij=x1;j<=x2;++j)
            {
                if(ans<dp[j][y1][y2])
                {
                    ans=dp[j][y1][y2];
                }
            }
    //        printf("%d
    ",ans);
            out(ans);
            putchar(10);
        }
        return 0;
    }
  • 相关阅读:
    375D.Tree and Queries(树上启发式合并+离线)
    600E.Lomsat gelral (树上启发式合并)
    741D.Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(树上启发式合并+状压)
    Nowcoder13249.黑白树(树形DP)
    Nowcoder51179.选课(树形背包)
    Nowcoder20811.蓝魔法师(树形背包)
    Nowcoder19782.Tree(树形DP+逆元)
    Gym102292M.Monster Hunter(树形背包+滚动数组)
    大数据运维(61)Linux环境安装PostgreSQL-10.1
    大数据运维(60)Hive on Spark配置
  • 原文地址:https://www.cnblogs.com/ztz11/p/9877547.html
Copyright © 2020-2023  润新知