首页 > 其他分享 >abc260_g Scalene Triangle Area 题解

abc260_g Scalene Triangle Area 题解

时间:2023-05-16 13:48:04浏览次数:56  
标签:Triangle int 题解 sum 矩阵 cin 差分 Scalene 2010

题目传送门

题意

给定一个大小为 \(n\times n\) 的字符矩阵,每个字符为 X 或者 O

对于一个位于 \((x,y)\) 的字符 o 和一个格子 \((u,v)\),如果满足以下条件,那么 \((u,v)\) 就可以被 \((x,y)\) 控制。

  • \(x \leqslant u \leqslant n\),\(y \leqslant v \leqslant n\)。
  • \((u-x)+\frac{v-y}{2} < m\)。

给定 \(m\) 和询问数 \(Q\),每次询问给定 \(u\) 和 \(v\),求有多少个格子可以控制 \((u,v)\)。

思路

分为两种做法。

0x00

推一推式子,可以发现:

  • 第 \(x\) 行第 \((y - 2 \times m) \sim y\) 列的 O 都可以控制 \((x,y)\)。
  • 第 \(x - 1\) 行第 \((y - 2 \times (m - 1)) \sim y\) 列的 O 都可以控制 \((x,y)\)。
  • 以此类推。
  • 第 \(x - m + 1\) 行第 \(y - 1\) 列与第 \(y\) 列的 O 可以控制 \((x,y)\)。
  • 第 \(1 \sim (x - m)\) 行没有可以控制 \((x,y)\) 的格子。

做法就出来了,对于每次询问在线求答案即可。

还有一个小问题,枚举每一行和每一列求答案是 \(O(n^2)\) 的,但每一行对答案有贡献的部分是一个区间,可以用前缀和优化,总时间复杂度为 \(O(n^2+ Q\times n)\),并不是最优解法,但可以过此题。

#include <iostream>

using namespace std;

int n, m, q, x, y, sum[2010][2010];
char c;

int main () {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      cin >> c;
      sum[i][j] = sum[i][j - 1] + (c == 'O'); // n 行的前缀和
    }
  }
  for (cin >> q; q; q--) {
    cin >> x >> y;
    int cnt = 0;
    for (int i = 0; i < m && x - i; i++) { // 枚举每一行,如果超出矩阵范围就退出循环
      cnt += sum[x - i][y] - sum[x - i][max(0, y - 2 * (m - i))]; // 前缀和
    }
    cout << cnt << '\n';
  }
  return 0;
}

0x01

二维差分。

对于一个位于 \((x,y)\) 的 O,可以控制的范围如上,其他的自己推一下(

先对于每一行列差分一下,变成下图:

观察上图,可以发现:第一列可以轻松的用行差分优化,但后面的 \(-1\) 怎么办呢?

我们要引入一个差分思想:一个不行就两个!

把这个差分矩阵拆成两个,在最后还原时将两个矩阵加起来。

左边矩阵差分点只有两个,可以 \(O(1)\) 处理差分,可右边怎么办呢?

仔细观察一下,欸,\(-1\) 的位置有规律!

将右边矩阵优化成下图:

差分矩阵通过前缀和思想还原原矩阵,上图每次只要加上 \((x - 1,y + 2)\) 的值就可以了,还原原矩阵时需要将两个差分矩阵加起来,再对它进行列前缀和即可,时间复杂度 \(O(n^2+Q)\)。

具体实现看代码。

#include <iostream>

using namespace std;

int n, m, q, x, y, sum[2010][2010], num[2010][12010][2]; // 注意数组的大小
char c;

int main () {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      cin >> c;
      if (c == 'O') {
        num[i][j][0]++, num[min(n + 1, i + m)][j][0]--; // 左边矩阵
        num[i][j + 2 * m][1]--, num[min(n + 1, i + m)][j][1]++; // 右边矩阵
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n + 2 * m; j++) {
      num[i][j][1] += num[i - 1][j + 2][1]; // 左右矩阵各自进行还原
      num[i][j][0] += num[i - 1][j][0];
      if (j <= n) {
        sum[i][j] = sum[i][j - 1] + num[i][j][1] + num[i][j][0]; // 最终的矩阵还原
      }
    }
  }
  for (cin >> q; q; q--) {
    cin >> x >> y;
    cout << sum[x][y] << '\n';
  }
  return 0;
}

标签:Triangle,int,题解,sum,矩阵,cin,差分,Scalene,2010
From: https://www.cnblogs.com/lw0-blog/p/17405355.html

相关文章

  • 前端传递参数与后端接收的类属性不一致问题解决办法
    使用@JsonAlias作用是在反序列化的时候可以让Bean的属性接收多个json字段的名称。可以加在字段上或者getter和setter方法上。publicclassUser{ @JsonAlias({"name","user"}) privateStringusername; privateStringpassword; privateIntegerage;}这样子......
  • JOISC 2018 题解
    没做计算几何题和提交答案题。JOISC2018Day1ConstructionofHighway道路建设注意到题目中的操作相当于就是到根的路径染色,我们离线下来进行树剖,每条重链维护连续段,然后显然均摊会修改\(O(n\logn)\)段。我们每次修改时可以取出所有连续段,然后题目问逆序对数,我们对这些连续......
  • ORA-02049:超时:分布式事务处理等待锁 问题解决
    数据库添加DBLink后,很容易出现一个问题:ORA-02049:超时:分布式事务处理等待锁ORA-02063:紧接着line(起自ODS_LINK) 问题原因分析:第一次执行操作后出错,数据库没有提交或回退,未关闭原有数据库窗口,重新打开新窗口执行数据插入操作,报ORA-02049错误。解决办法:数据库登陆管理员账号查看1、......
  • 跨域问题解决记录Access-Control-Allow-Origin方法
      more_set_headers 'Access-Control-Allow-Origin: http://devops.opsenv.com';    more_set_headers 'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS';    more_set_headers 'Access-Control-Allow-Headers: Authorization,DNT,......
  • el-popover无法弹出的问题解决
    1、不能再el-popover上⾯使⽤v-if进⾏显⽰隐藏,应该⽤v-show2、在每⼀个el-popover上都增加⼀个ref确定每个el-popover都是唯⼀的,:ref="`node-popover-${scope.row.id}`"3、需要使⽤slot="reference"定义由哪个元素触发事件。除此之外,还有一种特殊情况就是在table使用el-popover也......
  • execjs - 编码报错问题解决方案
    当在Python中运行execjs时遇到编码问题,可能是由于JS代码中使用了非UTF-8编码。为了解决这个问题,您可以尝试以下两种方案最直接方法需要修改Subprocess中的Enconding为"Utf-8"将JS代码转换为UTF-8编码您可以在JS代码中将所有字符串转换为UTF-8编码。例如,您可以在JS代码文件......
  • luogu P4690 [Ynoi2016] 镜中的昆虫 题解
    P4690[Ynoi2016]镜中的昆虫题解题意维护一个长为 \(n\) 的序列 \(a_i\),有 \(m\) 次操作。将区间 \([l,r]\) 的值修改为 \(x\)。询问区间 \([l,r]\) 出现了多少种不同的数,也就是说同一个数出现多次只算一个。题解感觉这道题还是比较有意思的,像是一堆套路......
  • POJ--1163 The Triangle(DP)
    记录10:432023-5-15http://poj.org/problem?id=1163reference:《挑战程序设计竞赛(第2版)》第二章练习题索引p135DescriptionFigure1showsanumbertriangle.Writeaprogramthatcalculatesthehighestsumofnumberspassedonaroutethatstartsatthetopa......
  • NOIP 2023 模拟赛五 题解
    A.[NOIP2023模拟赛五ByFXTA]简单数学题summarization给出一个值域为\([1,m]\)的正整数序列\(a_{1\simn}\),序列中的数各不相同,求出使\(a_i^2+a_j\)为完全平方数的\((i,j)\)的对数。solution实际上就是求\(x^2+y=z^2\quad(x,y,z\in\mathbb{N}^+)\)的\((x,y)\)......
  • P4555 最长双回文串 题解
    首先用manacher处理一下。然后我们可以枚举断点,问题变为求任意一个点为起点或终点的最长回文串,我们可以在manacher过程中更新这个值。但这样做是不对的。因为我们只用了最长的回文串更新,未考虑一个点在大回文串内部的情况,所以我们可以考虑第二次递推,以\(l\)数组(起点最长)为......