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

 

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\n", t.tn[a][b]); }
    }

    return 0;
}
MAZE

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

 

 posted on 2019-07-23 15:46  Nonad  阅读(166)  评论(0编辑  收藏  举报