【51Nod1555】布丁怪

题面

51Nod

题目大意:

给你一个\(n\times n\)的棋盘以及\(n\)个棋子,每个棋子坐标为\((x_i,y_i)\),保证棋盘的每一行或一列都有且仅有一个棋子,问你有多少个正方形框住的棋子数数值上等于正方形的边长。

其中\(1\leq n\leq 3\times 10^5,1\leq x_i,y_i\leq n\)。

题解

首先转化一下题面,题面变为:

给你一个长度为\(n\)的数组\(a\),问你有多少个区间\([l,r]\)满足\(\max_{i=l}^ra_i-\min_{i=l}^ra_i+1=r-l+1\)。

对于这样子的一个东西,我们考虑分治。

那么我们就是要合并\([l,mid],[mid+1,r]\)这两个区间。

因为和最大/小值有关,我们对于\([l,mid]\)维护后缀\(\min/\max\),\([mid+1,r]\)维护前缀\(\min/\max\),然后按照最大/小值出现位置分类讨论一下。

  • \(min,max\)在同一边,那么对于每个位置\(i\)可以确定出一个唯一与之确定的左/右端点,只需对左/右区间分别扫一遍即可。
  • \(min,max\)不在同一边,那么我们假定左边取到\(\min\),右边取到\(\max\),那么一个满足条件的区间需要满足\(\max-\min=r-l\),

    也就是说\(\min-l=\max-r\),可以对于每个\(\min-l,\max-r\)放进桶里维护。左\(\max\)右\(\min\)的情况同理。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 3e5 + 5, T = 3e5;
int N, a[MAX_N], mn[MAX_N], mx[MAX_N];
int bln[MAX_N << 2];
long long ans = 0; void Div(int l, int r) {
if (l == r) return (void)(++ans);
int mid = (l + r) >> 1;
Div(l, mid), Div(mid + 1, r);
mn[mid] = mx[mid] = a[mid];
for (int i = mid - 1; i >= l; i--) {
mn[i] = min(mn[i + 1], a[i]);
mx[i] = max(mx[i + 1], a[i]);
}
mn[mid + 1] = mx[mid + 1] = a[mid + 1];
for (int i = mid + 2; i <= r; i++) {
mn[i] = min(mn[i - 1], a[i]);
mx[i] = max(mx[i - 1], a[i]);
}
for (int i = mid; i >= l; i--) {
int len = mx[i] - mn[i] + 1;
int pos = mid + (len - (mid - i + 1));
if (pos <= mid || pos > r) continue;
if (mx[pos] >= mn[i] && mx[pos] <= mx[i] &&
mn[pos] >= mn[i] && mn[pos] <= mx[i]) ++ans;
}
for (int i = mid + 1; i <= r; i++) {
int len = mx[i] - mn[i] + 1;
int pos = mid - (len - (i - mid + 1));
if (pos > mid || pos < l) continue;
if (mx[pos] >= mn[i] && mx[pos] <= mx[i] &&
mn[pos] >= mn[i] && mn[pos] <= mx[i]) ++ans;
}
int pl = mid + 1, pr = mid + 1;
for (int i = mid; i >= l; i--) {
while (pr <= r && mn[i] < mn[pr]) bln[mx[pr] - pr + T]++, ++pr;
while (pl < pr && mx[i] > mx[pl]) bln[mx[pl] - pl + T]--, ++pl;
ans += bln[mn[i] - i + T];
}
for (int i = pl; i < pr; i++) bln[mx[i] - i + T]--;
pl = pr = mid;
for (int i = mid + 1; i <= r; i++) {
while (pr >= l && mn[i] < mn[pr]) bln[mx[pr] + pr]++, --pr;
while (pl > pr && mx[i] > mx[pl]) bln[mx[pl] + pl]--, --pl;
ans += bln[mn[i] + i];
}
for (int i = pl; i > pr; i--) bln[mx[i] + i]--;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
N = gi(); for (int i = 1; i <= N; i++) a[gi()] = gi();
Div(1, N);
printf("%lld\n", ans);
return 0;
}

【51Nod1555】布丁怪的更多相关文章

  1. 题解[51nod1555] 布丁怪

    题解[51nod1555] 布丁怪 题面 解析 本文参考这位dalao的题解 首先有一个巧妙的转换, 开一个数组记录每个横坐标的纵坐标, 简单来说就是对于点(x,y),令a[x]=y. 于是问题就变成 ...

  2. 51Nod 1555 布丁怪

    题目描述: 布丁怪这一款游戏是在一个n×n 的矩形网格中进行的,里面有n个网格有布丁怪,其它的一些格子有一些其它的游戏对象.游戏的过程中是要在网格中移动这些怪物.如果两个怪物碰到了一起,那么他们就会变 ...

  3. Codeforces 436D Pudding Monsters

    题意简述 开始有无限长的一段格子,有n个格子种有布丁怪兽,一开始连续的布丁怪兽算一个布丁怪兽. 每回合你可以将一个布丁怪兽向左或右移动,他会在碰到第一个布丁怪兽时停下,并与其合并. 有m个特殊格子,询 ...

  4. [CF436D]Pudding Monsters

    题目大意:有一个长度为$2\times 10^5$的板,有$n(n\leqslant 10^5)$个格子$a_1,\dots,a_n$有布丁怪兽,一开始连续的怪兽算一个怪兽,有$m(m\leqslan ...

  5. 第一个独立开发的游戏 怪斯特:零 已经上线APP STORE!

    今天是个值得纪念的日子,而且是双喜临门 2年多来的摸爬滚打,终于有了回报 第一喜:自己独立开发的游戏 怪斯特:零 已经通过审核并上架APP STORE! 第二喜:迈入了自己期待2年之久的游戏行业,年后 ...

  6. 1483:[HNOI]2009 梦幻布丁 - BZOJ

    Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input 第 ...

  7. bzoj 1483 [HNOI2009]梦幻布丁(链表+启发式合并)

    1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1818  Solved: 761[Submit][Status ...

  8. 数据结构(启发式合并):HNOI 2009 梦幻布丁

    Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input 第 ...

  9. 【BZOJ1483】【链表启发式合并】梦幻布丁

    Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input 第 ...

随机推荐

  1. ASP.NET Core快速入门(第2章:配置管理)- 学习笔记(转载)

    原文地址:https://mp.weixin.qq.com/s?__biz=MjM5NjMzMzE2MA==&mid=2451733443&idx=2&sn=6d01721c5 ...

  2. (四十二)golang--协程之间通信的方式

    假设我们现在有这么一个需求: 计算1-200之间各个数的阶乘,并将每个结果保存在mao中,最终显示出来,要求使用goroutime. 分析: (1)使用goroutime完成,效率高,但是会出现并发/ ...

  3. 【mysql报错】MySQL host is blocked because of many connection errors; 解决方法

    MySQL host is blocked because of many connection errors; 报错 环境 操作系统:Linux 数据库:mysql5.7.27 错误提示 jHost ...

  4. SiftingAppender logback 动态 输出 日志 到指定日志文件

    SiftingAppender https://www.mkyong.com/logging/logback-different-log-file-for-each-thread/

  5. 最新整理的spring面试题从基础到高级,干货满满

    最新整理的spring面试题从基础到高级,干货满满 前言: 收藏了一些关于Spring的面试题,一方面是为了准备找工作的时候看面试题,另一方面,通过面试题的方式加深一些自己的理论知识. spring ...

  6. jvm常用排错命令

    jvm命令很多,有一篇博客整理的非常全 https://www.cnblogs.com/ityouknow/p/5714703.html.我只列举一些常用的排错用到的. jps   -l   -v  ...

  7. java斐波那契数列的顺序输出

    斐波那契数列,即1.1.2.3.5......,从第三个数开始包括第三个数,都为这个数的前两个数之和,而第一第二个数都为1. 下面是java输出斐波那契数列的代码: import java.util. ...

  8. Vue计算属性computed的全面解析

    前言 一直以来对computed这个计算属性都只停在一个大概的认知中,最近特意仔细研读相关资料,亲测后逐渐了解了其特性. 正文 computed 特点: 1.初始化/依赖属性(即data属性)改变时执 ...

  9. maven 学习---使用“mvn site-deploy”部署站点

    这里有一个指南,向您展示如何使用“mvn site:deploy”来自动部署生成的文档站点到服务器,这里通过WebDAV机制说明. P.S 在这篇文章中,我们使用的是Apache服务器2.x的WebD ...

  10. JS 判断设备来源

    1.js代码判断当前设备: function deviceType(){ var ua = navigator.userAgent; var agent = ["Android", ...