zoukankan      html  css  js  c++  java
  • [补]2019nowcoder牛客第二场E、H(upd0730)

     

    ↑懒懒的我终于换成折叠态代码,然而不知道怎么把这个框框弄掉。。)

    H second large rectangle

    0725upd:参考于https://www.cnblogs.com/DeaphetS/p/11229389.html

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    const int maxn = 1000 + 5;
    int l[maxn][maxn], r[maxn][maxn], h[maxn][maxn];
    bool mp[maxn][maxn];
    int n, m, ml, mr;
    int ma, sma, mlx, mly,mrx,mry, slx, sly,srx,sry, curm,curs, curx, cury;
    
    int main()
    {
        cin >> n>>m;
        char a;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++) {
                cin >> a;
                mp[i][j]=a-'0';
                if (mp[i][j]) {
                    l[i][j] = r[i][j] = j;
                    h[i][j] = 1;//悬线法初始化处理
                }
            }
    
        for (int i = 1; i <= n; i++) {
            for (int j = 2; j <= m; j++)
                if (mp[i][j] && mp[i][j - 1])l[i][j] = l[i][j - 1];//左推
            for (int j = m - 1; j >= 1; j--)
                if (mp[i][j] && mp[i][j + 1])r[i][j] = r[i][j + 1];//右推
            for (int j = 1; j <= m; j++) {
                if (i != 1 && mp[i][j] && mp[i - 1][j]) {
                    h[i][j] = h[i - 1][j] + 1;
                    l[i][j] = max(l[i][j], l[i - 1][j]);
                    r[i][j] = min(r[i][j], r[i - 1][j]);//画框框
                }
                int cur = (r[i][j] - l[i][j] + 1) * h[i][j];//当前面积
                int lx, ly, rx, ry;
                lx = i - h[i][j] + 1; rx = i;
                ly = l[i][j]; ry = r[i][j];//左上角与右下角坐标
      ·                //↓判断是否是同一个矩形!
                if (cur >= curm && (lx != mlx || ly != mly || rx != mrx || ry != mry)) {
                        curs = curm, curm = cur; 
                        slx = mlx, mlx = lx;
                        sly = mly, mly = ly;
                        srx = mrx, mrx = rx;
                        sry = mry, mry = ry;
                    }//更新最大面积与次大面积
                if(cur>curs&&cur<curm){
                        slx = lx, sly = ly;
                        srx = rx, sry = ry;
                        curs = cur;
                    }//更新次大面积
                curx = (rx - lx) * (ry - ly + 1), cury = (ry - ly) * (rx - lx + 1);
                if (curx > curs)  curs = curx, slx = lx + 1, sly = ly, srx = rx, sry = ry;
                if (cury > curs)  curs = cury, slx = lx, sly = ly + 1, srx = rx, sry = ry;
            //宽和长分别减一行看看是不是次大
            }
        }
        cout << curs << endl;
    
        return 0;
    }
    second large rectangle

    赛中  Thor:你之前不是做过类似的题吗?看看这题

        红小豆内心:啊我终于能写题了!  实践后:n4、n3这时间复杂度不行啊。。。

    赛后学习预备知识:悬线法o(n2)记录当前点所在悬线的左边界和右边界以及向上可达的高(该条悬线的高)

    赛后补题写了个朴素的悬线法(作用都是一样的呀(#`O′))然后只过60%的数据。在面向题解编程的过程中,发现不是悬线法处理的问题,是同一个矩形的判断的问题(就是那两个条件奇奇怪怪的if)。因为不想写结构体的 . 于是开了一堆变量。。

    还有用单调栈做的大佬,emmm,单调栈,了解一下。

    本来想整场比赛补完再一起更新的,结果补到B题开始学习数学基础,暂且告辞_(:з」∠)_

    0730upd:

    E  MAZE

      参考于:https://www.cnblogs.com/DeaphetS/p/11222740.html

      又是快乐的线段树,加上了快乐的转移矩阵,甚至还有快乐的输入方式,三倍的快乐

      从前有一个东西叫做转移矩阵,在红小豆目前看来就像是建图的时候的邻接矩阵。

      比如说,对于迷宫 0 0 0 1 0 第一行的转移矩阵长这样  1 1 1 0 0

               1 0 0 1 0              1 1 1 0 0

       第二行的长这样 0 0 0 0 0                   1 1 1 0 0

               0 1 1 0 0                   0 0 0 0 0

               0 1 1 0 0              0 0 0 0 1

                    0 0 0 0 0

                    0 0 0 0 1  从第一行到第二行就进行矩阵乘运算

           得到了这个东西  0 0 0 0 0  获得了方案数呢,sugoi!

                       2 2 2 0 0

                          2 2 2 0 0

                          0 0 0 0 0

                                               0 0 0 0 1    线代飘过的人需要好好学线代了_(:з」∠)_

      那么,对于每次询问,我们需要做的就是将第一行开始到第n行的转移矩阵乘起来,(1,a)到(n,b)的方案数就是矩阵(a,b)的结果

      所以要进行的操作有获取单位矩阵、获取迷宫改变后的对应行的矩阵并更新、进行矩阵乘法、查询某几行的转移矩阵和输入(认真脸

      区间查询区间修改使用了线段树,脑补出好大一棵满是矩阵的线段树感到莫名有趣wwwww

      输入迷宫的时候尝试了两种方法,需要吞回车的getchar不太适合这里呢,两种方法运行了一下,getchar那份慢了200ms

      写线段树的时候试图偷懒,结果搞不清左子右子和左边界右边界的区别了,从头再来orz

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    int n, m, q;
    bool mp[50005][15];
    char s[50005];
    const LL mod = 1e9 + 7;
    
    struct mx {
        LL tn[15][15];
    
        void init()
        {
            for (int i = 1; i <= m; i++)
                for (int j = 1; j <= m; j++)
                    tn[i][j] = 0;
        }
    
        mx operator* (const mx& t)const {
            mx res;
            res.init();
    
            for (int i = 1; i <= m; i++)
                for (int j = 1; j <= m; j++)
                    for (int k = 1; k <= m; k++)
                        res.tn[i][j] = (res.tn[i][j] + tn[i][k] * t.tn[k][j] % mod) % mod;
    
            return res;
        }
    
        void e()
        {
            for (int i = 1; i <= m; i++)
                for (int j = 1; j <= m; j++)
                    tn[i][j] = (i == j);                
        }
    
        void get(int i)
        {
            init();
            int l = 1, r = 1;
            for (int j = 1; j <= m; j++) {
                if (mp[i][j]) { l = r = j + 1; continue; }
                while (r <= m && mp[i][l] == mp[i][r])r++;
                r--;
                for (int k = l; k <= r; k++)tn[k][j]++;
            }
        }
    };
    
    struct st
    {
    #define ls i<<1
    #define rs i<<1|1
    
        struct node {
            mx v;
            int l, r;
        }po[50005 << 2];
    
        void puu(int i) { po[i].v = po[ls].v * po[rs].v; }
    
        void build(int l, int r, int i)
        {
            po[i].l = l, po[i].r = r;
            if (l == r) {
                po[i].v.get(l);
                return;
            }
            int mid = (l + r) >> 1;
            build(l, mid, ls);
            build(mid + 1, r, rs);
            puu(i);
        }
    
        void cha(int i, int c)
        {
            int  l = po[i].l, r = po[i].r;
            if (l == c && r == c) { po[i].v.get(c); return; }
            int mid = (l + r) >> 1;
            if (mid >= c)cha(ls, c);
            else cha(rs, c);
            puu(i);
        }
    
        mx qy(int l, int r, int i)
        {
            if (po[i].l >= l && r >= po[i].r)return po[i].v;
            mx res; res.e();
            int mid = (po[i].l + po[i].r) >> 1;
            if (mid >= l)res = res * qy(l, r, ls);
            if (mid < r)res = res * qy(l, r, rs);
            return res;
        }
    
    }seg;
    
    int main()
    {
        scanf("%d%d%d", &n, &m, &q);
        /*for (int i = 1; i <= n; i++){
            scanf("%s", s+1);
            for (int j = 1; j <= m; j++)
                mp[i][j] = s[j] - '0';
        }*/
    
        getchar();//吞回车
        for (int i = 1; i <= n; i++, getchar())//吞回车+1
            for (int j = 1; j <= m; j++)
                mp[i][j] = getchar() - '0';
    
        seg.build(1, n, 1);
        for (int i = 0; i < q; i++) {
            int p, a, b;
            scanf("%d%d%d", &p, &a, &b);
            if (p == 1) { mp[a][b] ^= 1; seg.cha(1, a); }
            else { mx t = seg.qy(1, n, 1); printf("%lld
    ", t.tn[a][b]); }
        }
    
        return 0;
    }
    MAZE

      今天依然是起名不超过三个字符的我(๑•̀ㅂ•́)و✧(永远的build除外)

  • 相关阅读:
    java并发编程 线程间协作
    博客园添加目录,导航,回到顶部
    汉诺塔递归实现
    java并发编程 线程基础
    Flink中算子进行Chain的规则分析(最新代码,源码版本大于1.11.2)
    Flink流处理程序在Local模式下的运行流程源码分析
    Flink-DataStream流处理应用(Local模式下)运行流程-源码分析
    Flink Streaming基于滚动窗口的事件时间分析
    Spark-2.3.2 Java SparkSQL的自定义HBase数据源
    Spark-2.3.2 HBase BulkLoad
  • 原文地址:https://www.cnblogs.com/non-/p/11232217.html
Copyright © 2011-2022 走看看