N×M的棋盘(M,N<=500)中,每个格子有一个颜色(颜色数1~9)

P次操作(P<=1000),每次给出两个相邻的位置(保证颜色不同,两个格子有一条公共边),把这两个格子交换。

定义每次交换的分值为:通过这次交换能够形成的最大矩形的面积。

求每次操作后的分值。

【题解】

      ①预处理类似于悬线法,维护u,d,l,r

      ②由于需要包含当前点,因此可以向两侧维护单调递减序列(大了就削掉)。

      ③维护双指针,根据单调性,可以O(n)推出最大的矩形面积。

(ZJ亲手绘制)

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 505
using namespace std;
int mp[MAXN][MAXN];
int Up[MAXN][MAXN],Down[MAXN][MAXN],Left[MAXN][MAXN],Right[MAXN][MAXN];
int n,m;
void calculation_row(int i){
for(int j=1;j<=m;j++)
if(j==1||mp[i][j-1]!=mp[i][j]) Left[i][j]=1;
else Left[i][j]=Left[i][j-1]+1;
for(int j=m;j>=1;j--)
if(j==m||mp[i][j+1]!=mp[i][j]) Right[i][j]=1;
else Right[i][j]=Right[i][j+1]+1;
}
void calculation_column(int j){
for(int i=1;i<=n;i++)
if(i==1||mp[i-1][j]!=mp[i][j]) Up[i][j]=1;
else Up[i][j]=Up[i-1][j]+1;
for(int i=n;i>=1;i--)
if(i==n||mp[i+1][j]!=mp[i][j]) Down[i][j]=1;
else Down[i][j]=Down[i+1][j]+1;
}
void readin(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&mp[i][j]);
for(int i=1;i<=n;i++)
calculation_row(i);
for(int j=1;j<=m;j++)
calculation_column(j);
}
int get_lr(int x,int y,int t[MAXN][MAXN]){
static int h[MAXN],v[MAXN],cnt,p,ans,now;
ans=t[x][y];
cnt=0; p=1; now=t[x][y]; h[++cnt]=t[x][y]; v[cnt]=1;
for(int i=x-1;i>=x-Up[x][y]+1;i--){
if(t[i][y]<h[cnt]) h[++cnt]=t[i][y];
v[cnt]=x-i+1;
}
for(int i=x+1;i<=x+Down[x][y]-1;i++){
now=min(now,t[i][y]);
while(p+1<=cnt&&h[p+1]>=now) p++;
ans=max(ans,(i-x+v[p])*now);
}
cnt=0; p=1; now=t[x][y]; h[++cnt]=t[x][y]; v[cnt]=1;
for(int i=x+1;i<=x+Down[x][y]-1;i++){
if(t[i][y]<h[cnt]) h[++cnt]=t[i][y];
v[cnt]=i-x+1;
}
for(int i=x-1;i>=x-Up[x][y]+1;i--){
now=min(now,t[i][y]);
while(p+1<=cnt&&h[p+1]>=now) p++;
ans=max(ans,(x-i+v[p])*now);
}
return ans;
}
int get_ud(int x,int y,int t[MAXN][MAXN]){
static int h[MAXN],v[MAXN],cnt,p,ans,now;
ans=t[x][y];
cnt=0; p=1; now=t[x][y]; h[++cnt]=t[x][y]; v[cnt]=1;
for(int j=y-1;j>=y-Left[x][y]+1;j--){
if(t[x][j]<h[cnt]) h[++cnt]=t[x][j];
v[cnt]=y-j+1;
}
for(int j=y+1;j<=y+Right[x][y]-1;j++){
now=min(now,t[x][j]);
while(p+1<=cnt&&h[p+1]>=now) p++;
ans=max(ans,(j-y+v[p])*now);
}
cnt=0; p=1; now=t[x][y]; h[++cnt]=t[x][y]; v[cnt]=1;
for(int j=y+1;j<=y+Right[x][y]-1;j++){
if(t[x][j]<h[cnt]) h[++cnt]=t[x][j];
v[cnt]=j-y+1;
}
for(int j=y-1;j>=y-Left[x][y]+1;j--){
now=min(now,t[x][j]);
while(p+1<=cnt&&h[p+1]>=now) p++;
ans=max(ans,(y-j+v[p])*now);
}
return ans;
}
void printmap(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
printf("%d ",mp[i][j]);
printf("\n");
} }
void work(){
int k,x1,x2,y1,y2,ans;
scanf("%d",&k);
while(k--){
ans=0;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
swap(mp[x1][y1],mp[x2][y2]);
calculation_row(x1);
calculation_column(y1);
if(x1==x2){
calculation_column(y2);
if(y1>y2) swap(y1,y2);
ans=max(ans,get_lr(x1,y1,Left));
ans=max(ans,get_lr(x2,y2,Right));
}
else{
calculation_row(x2);
if(x1>x2) swap(x1,x2);
ans=max(ans,get_ud(x1,y1,Up));
ans=max(ans,get_ud(x2,y2,Down));
}
printf("%d\n",ans);
//printmap();
}
}
int main(){
//freopen("2050.in","r",stdin);
readin();
work();
return 0;
}//*ZJ

.

【ZJ选讲·钻石游戏】的更多相关文章

  1. 【ZJ选讲·画山】

    给出一张纸(N × M),你要在上面画山,但不能画出界(N,M<=100) Like this: 起点为(0,0),终点为(N,0) 给出w种线段画法(x,y),表示用了这种画法后,笔迹末 ...

  2. 【ZJ选讲·字符串折叠】

    给一个字符串(len<=100) 把这个字符串折叠(就是压缩) 记 X(子串) 表示重复 X次该子串 比如 3(orz)  orzorzorz  来点神奇例子: AAAAAAAAAA ...

  3. 【ZJ选讲·压缩】

    给一个由小写字母组成的字符串(len<=50) 我们可以用一种简单的方法来压缩其中的重复信息. 用M,R两个大写字母表示压缩信息 M标记重复串的开始, R表示后面的一段字符串重复从上一个 ...

  4. 【ZJ选讲·调整】

    给出n个点,m条有向边(带正权),起点S,终点T.(n<=2000,m<=30000) 再给出一个k,表示可以把最多k条边的权值调整为任意非负整数.(k<=100) 问是否可以通 ...

  5. 【ZJ选讲·BZOJ 5073】

    小A的咒语 给出两个字符串A,B (len<=105) 现在可以把A串拆为任意段,然后取出不超过 x 段,按在A串中的前后顺序拼接起来 问是否可以拼出B串. [题解]       ①如果遇 ...

  6. 【ZJ选讲·BZOJ 5071】

    小A的数字 有一串数字A1 ,A2,--,An,每次可以进行如下骚操作: 选择一个数字i,将(Ai-1,Ai,Ai+1)变为(Ai-1+Ai,-Ai,Ai+1+Ai), (特别地,若i=N,则( ...

  7. 2019暑期金华集训 Day6 杂题选讲

    自闭集训 Day6 杂题选讲 CF round 469 E 发现一个数不可能取两次,因为1,1不如1,2. 发现不可能选一个数的正负,因为1,-1不如1,-2. hihoCoder挑战赛29 D 设\ ...

  8. DP选讲

    $DP$选讲直接上题吧放个题单[各省省选DP](https://www.luogu.com.cn/training/151079)$P5322[BJOI2019]$排兵布阵一眼题,考虑$dp[i][j ...

  9. PJ可能会用到的动态规划选讲-学习笔记

    PJ可能会用到的动态规划选讲-学习笔记 by Pleiades_Antares 难度和速度全部都是按照普及组来定的咯 数位状压啥就先不讲了 这里主要提到的都是比较简单的DP 一道思维数学巧题(补昨天) ...

随机推荐

  1. mysql更新返回值问题(更新内容跟之前内容一样,返回0)

    mysql更新返回值问题 问: 有一界面要更新个人信息,有几十个text标签需要填写假设有一用户从用户列表点修改进入了修改页面,但又没有修改什么,马上点击保存这时,因为text标签非常多,不能够一一判 ...

  2. ThinkPHP中的pathinfo模式和URL重写

    语文一直不太好,要我怎么解释这个pathinfo模式还真不知道怎么说,那就先来一段代码说下pathinfo模式吧 http://serverName/appName/module/action/id/ ...

  3. 幸运三角形 南阳acm491(dfs)

    幸运三角形 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 话说有这么一个图形,只有两种符号组成(‘+’或者‘-’),图形的最上层有n个符号,往下个数依次减一,形成倒 ...

  4. mac制作U盘启动器

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.所需工具及必要条件: 1. 首先需要一个大于16GB U盘. 2.电脑系统版本应该大于10.11.X(因为之前 ...

  5. 基于vue来开发一个仿饿了么的外卖商城(一)

    一.准备工作 1.大前提:已安装好node. npm. vue. vue-cli.stylus(此项目使用stylus来编译) 2.开发软件:Google Chrome(建议安装插件vue-devto ...

  6. 一步一步学Linq to sql(四):查询句法

    select 描述:查询顾客的公司名.地址信息 查询句法: var 构建匿名类型1 = from c in ctx.Customers select new { 公司名 = c.CompanyName ...

  7. LeetCode:24. Swap Nodes in Pairs(Medium)

    1. 原题链接 https://leetcode.com/problems/swap-nodes-in-pairs/description/ 2. 题目要求 给定一个链表,交换相邻的两个结点.已经交换 ...

  8. 20160120使用myeclipse一年开始转IntelliJ IDEA 15做以下总结

    20160120使用myeclipse一年开始费元星转IntelliJ IDEA 15做以下总结 1.输入psv就会看到一个psvm的提示,此时点击tab键一个main方法就写好了.psvm 也就是p ...

  9. ExtJs工具篇(3)——Aptana Studio3乱码的问题

            在Aptana Studio里面使用,发现输入的中文是乱码,在浏览器中浏览也是乱码,想着肯定是编码的问题,但是一直没有找到在那个地方设置.以为汉化后就可以了,没想到汉化后竟然还是乱码, ...

  10. Bootstrap开发漂亮的前端界面之实现原理

    引:Bootstrap采用的是一个“响应式”设计.响应式Web 设计是一个让用户通过各种尺寸的设备浏览网站获得良好的视觉效果的方法.例如,您先在计算机显示器上浏览一个网站,然后再智能手机上浏览,智能手 ...