【Luogu】P1169棋盘制作(单调栈)

  题目链接

  唉……这种题放在NOIP以前我是会做的……但是为什么现在反而不会了……

  单调栈。预处理每个点向上能扩展的最大距离,左右用两遍单调栈扫一遍。注意边界。

  

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;

inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch==‘-‘)    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-‘0‘;
        ch=getchar();
    }
    return num*f;
}

int q[2010][2010];
int d[2010][2010][2];
int w[2020];int s[2020];
int stack[2020],top;
int ans;
int cnt;

int main(){
    int n=read(),m=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            q[i][j]=read()^((i+j+1)%2);
            int now=q[i][j];
            d[i][j][now]=q[i-1][j]==now?d[i-1][j][now]+1:1;
        }
    for(int i=1;i<=n;++i){
        memset(w,0,sizeof(w));    top=0;
        for(int j=1;j<=m;++j){
            w[j]=j;
            while(top&&d[i][stack[top]][0]>d[i][j][0])    w[stack[top--]]=j-1;
            stack[++top]=j;
        }
        //while(top)    w[stack[top--]]=n;
        memset(s,0,sizeof(s));    top=0;
        for(int j=m;j>=1;--j){
            s[j]=j;
            while(top&&d[i][stack[top]][0]>d[i][j][0])    s[stack[top--]]=j+1;
            stack[++top]=j;
        }
        //while(top)    s[stack[top--]]=1;
        for(int j=1;j<=m;++j){
            ans=max(ans,(w[j]-s[j]+1)*d[i][j][0]);
            int MIN=min(w[j]-s[j]+1,d[i][j][0]);
            cnt=max(cnt,MIN*MIN);
        }
    }
    for(int i=1;i<=n;++i){
        memset(w,0,sizeof(w));    top=0;
        for(int j=1;j<=m;++j){
            w[j]=j;
            while(top&&d[i][stack[top]][1]>d[i][j][1])    w[stack[top--]]=j-1;
            stack[++top]=j;
        }
        //while(top)    w[stack[top--]]=n;
        memset(s,0,sizeof(s));    top=0;
        for(int j=m;j>=1;--j){
            s[j]=j;
            while(top&&d[i][stack[top]][0]>d[i][j][1])    s[stack[top--]]=j+1;
            stack[++top]=j;
        }
        //while(top)    s[stack[top--]]=1;
        for(int j=1;j<=m;++j){
            ans=max(ans,(w[j]-s[j]+1)*d[i][j][1]);
            int MIN=min(w[j]-s[j]+1,d[i][j][1]);
            cnt=max(cnt,MIN*MIN);
        }
    }
    printf("%d\n%d",cnt,ans);
    return 0;
}

原文地址:https://www.cnblogs.com/cellular-automaton/p/8315186.html

时间: 2024-08-29 20:09:44

【Luogu】P1169棋盘制作(单调栈)的相关文章

BZOJ1057[ZJOI2007]棋盘制作 [单调栈]

题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则. 小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一.小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大.

BZOJ 1057 ZJOI2007 棋盘制作 单调栈

题目大意:给定一个黑白两色的矩阵,求最大的黑白相间的子正方形和子矩阵 将奇数位置的点反色,然后就是求纯色的最大子正方形和子矩阵 将矩阵一层层剖分,每层上方是一段类似于▆▃▇▂▉的东西,用单调栈跑出每个点向左向右能拓展到的最大距离,更新答案即可 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 2020 using namespace

luogu 1169 棋盘制作(单调栈/悬线)

luogu 1169 棋盘制作(单调栈/悬线) 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳.而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则.小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一.小Q想在这种纸中裁减一部分作为新棋盘,

洛谷 P1169 [ZJOI2007]棋盘制作

2016-05-31 14:56:17 题目链接: 洛谷 P1169 [ZJOI2007]棋盘制作 题目大意: 给定一块矩形,求出满足棋盘式黑白间隔的最大矩形大小和最大正方形大小 解法: 神犇王知昆的悬线法 论文:浅谈用极大化思想解决最大子矩形问题 H[i][j]表示(i,j)向上最长连续多少距离不出现障碍点(悬线) L[i][j]表示H[i][j]这根悬线最多可以向左移到什么位置 R[i][j]表示H[i][j]这根悬线最多可以向右移到什么位置 递推方式看代码吧,很好理解的 1 //棋盘制作

单调栈模板题 luogu P2659

题目链接:https://www.luogu.org/problem/P2659 实际上就是要我们求出每个数字左右两边第一个小于它的数字位置,然后两个位置所在的开区间长度乘以这个数字,取最大值输出. 因为是求两边第一个小于a[i]的数字,所以我们弄一个递增(其实是不减小就可以了,可以有相同大小的元素)的单调栈,从栈底到栈顶的数字是依次增大的,在求的过程中要始终保持递增的性质.我们每次在数字入栈时求出数字左边第一个小于它的数字位置,在出栈的时候求出右边第一个小于它的数字位置,为什么是这样,看下面,

Luogu【P1901】发射站(单调栈)

题目链接 题目说明比自己矮的塔收不到自己的能量,摆明了就是单调栈呗. 把比自己矮的全都从栈里弹出去,于是碰到第一个比自己高的.让他接受自己发射的能量. 当然由于发射站发射的能量有两个方向,所以正反两遍. 然后 放代码. #include<cstdio> #include<cstdlib> #include<cctype> using namespace std; long long ans; inline long long max(long long a,long l

【Luogu】P2422良好的感觉(单调栈)

题目链接 写代码能力需要极大提升.我在五分钟之内想到了单调栈,然后花了一个小时的时间去看我单调队列为啥写错了…… 首先这题需要转换自己的思维.枚举所有“最小点”,然后看它往左往右最大能扩展多少. 维护一个单调递增的序列,弹栈时就会是这种情况: 设被弹出去的元素是s,那它为什么会被弹出去呢?因为它比当前元素大. 比当前元素大说明了什么呢?说明如果有一个区间以它为最小值,那这个区间向右扩展的极限就在当前元素前面.因为区间不能继续向右扩展,一扩展,区间就包含当前元素了,那元素s就不是最小值了,而我们这

BZOJ1057:[ZJOI2007]棋盘制作——题解

http://www.lydsy.com/JudgeOnline/problem.php?id=1057 https://www.luogu.org/problemnew/show/P1169 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋

1057: [ZJOI2007]棋盘制作

1057: [ZJOI2007]棋盘制作 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 2398  Solved: 1191[Submit][Status][Discuss] Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源 于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳.而我们的主人公小Q, 正是国际象棋的狂热爱好者.作为一个顶尖高手,他