首页 > 其他分享 >情书密码 题解

情书密码 题解

时间:2024-02-17 11:56:06浏览次数:35  
标签:树状 int 题解 情书 密码 数组 y1 x1 绝恋

题目描述

有消息称:绝恋找到了自己的Miss Right,正准备自己的表白。绝恋已经写好了情书,但为了避免其它人截获,他对情书进行加密。

为了打探绝恋的私密,你冒着生命危险终于搞到了这封情书。原以为可以轻易将情书解密,结果竟然发现聪明的绝恋并没有直接写出加密用的密码,而是在那粉红色的信纸背面写着“T=你的幸运数字”。

就这么放弃了吗?不,作为一个高智商的OIer,你决不轻言放弃。你还搞到了绝恋做密码时的草稿,通过一定的分析,你发现草稿中隐藏了绝恋的密码,具体规则如下:

草稿纸上写着一个N*M 的矩阵,每个位置都有一个数字C,绝恋对该矩阵不断进行操作,有时会修改某一位置的值,还不时计算出一个矩形内特定数字的个数作为密码的一部分,绝恋十分聪明,他进行了许多次这样的操作,因此密码也异常复杂,但是你已经下定决心要算出密码了,所以你一定要算出来!!

输入格式

第一行有两个数字N,M

接下来N 行,每行M 个数,第i+1 行第j 个数表示格子(i,j)的初始值。

接下来一个整数Q

接下来Q 行,每行描述一个操作

操作1:1 x y c,表示将格子(X,Y)的权值改为C

操作2:2 x1, x2, y1, y2,表示询问矩形内有多少个位置的权值为C。x1, x2分别为矩形横坐标中的最小值和最大值,y1, y2为矩形纵坐标中的最小值和最大值。

输出格式

对于每一个操作2,输出一个整数表示答案,每数一行。

样例

样例输入

3 3
1 2 3
3 2 1
2 1 3
3
2 1 2 1 2 1
1 2 3 2
2 2 3 2 3 2

样例输出

1
2

题解

拿到题,发现是在矩阵上进行单点修改和区间查询,很容易想到二维树状数组;

二维树状数组的概念和板子在这里不在赘述,这道题和板子最大的区别在于:1、它不是加上一个数,而是修改一个数;2、它求的不是前缀和,而是点出现的次数;

第一个实现简单,直接在单点修改时加上俩数差值即可;

但第二个如果要实现的话,需要维护一个差分数组,并在每一个区间遍历找每一个点判断是否合法;

貌似还不如打暴力(其实上述做法就是暴力);

当你TLE收获30分时,只能老老实实再换思路;

做DP的题时,相信大家都明白了维数的重要性,多开几维没坏处,有时候多开几维就能存储全我们想要的信息,而且大多数情况下不会MLE;

那本题,我们发现难点在于如何存储在一个区间内一个数的出现次数;

受DP的启发,我们可以将树状数组多开一维;

定义树状数组t[i][j][k]表示从(1, 1)到(i, j)这段区间,k这个数出现的次数(这确实很像DP);

当我们修改某个点的值时,只需将t[i][j][原来的值]--,将t[i][j][现在的值]++;

当我们查询某个区间某个数的出现次数时,只需查询树状数组在这一区间内的前缀和即可;

这样这个题就解决了;

代码

#include <iostream>
using namespace std;
int n, m, q;
int a[305][305];
int t[305][305][305]; //存储矩阵i,j中出现k的次数;
int lowbit(int x) {
	return x & (-x);
}
void add_dian(int x, int y, int past, int now) {
	for (int i = x; i <= n; i += lowbit(i)) {
		for (int j = y; j <= m; j += lowbit(j)) {
			t[i][j][past]--;
			t[i][j][now]++;
			if (t[i][j][past] < 0) t[i][j][past] = 0; //如果减超了,就赋值为0(主要应用于当past == 0时)(不写也行);
		}
	}
}
int ask_sum(int x, int y, int c) {
	int ans = 0;
	for (int i = x; i > 0; i -= lowbit(i)) {
		for (int j = y; j > 0; j -= lowbit(j)) {
			ans += t[i][j][c];
		}
	}
	return ans;
}
int main() {
	cin >> n >> m; //初始化一个n * m的全零矩阵;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> a[i][j];
			add_dian(i, j, 0, a[i][j]); //将0替换成a[i][j];
		}
	}
	cin >> q;
	int k, x, y, c, x1, y1;
	for (int i = 1; i <= q; i++) {
		cin >> k;
		if (k == 1) {
			cin >> x >> y >> c;
			add_dian(x, y, a[x][y], c);
			a[x][y] = c; //注意这里,原矩阵也要被更新,否则等再次更新此处时past的值会不对;
		}
		if (k == 2) {
			cin >> x1 >> x >> y1 >> y >> c;
			int ans = ask_sum(x, y, c) - ask_sum(x, y1 - 1, c) - ask_sum(x1 - 1, y, c) + ask_sum(x1 - 1, y1 - 1, c); //二维矩阵前缀和;
			cout << ans << endl;
		}
	}
	return 0;
}

后记:其实树状数组可以存很多种类的数,一般题目中不会给出,需要自己找;
当发现树状数组并不能完全存完我们想存的数时,不妨加几维,可能就可以解决;

标签:树状,int,题解,情书,密码,数组,y1,x1,绝恋
From: https://www.cnblogs.com/PeppaEvenPig/p/18017848

相关文章

  • CF484B题解
    朴素的办法是枚举每两个数然后更新取模的结果。时间复杂度为\(O(n^2)\)不能通过。这个朴素的过程可以看作枚举一个数然后找对其取模最大值的过程。我们可以枚举一个数,然后再枚举以它的倍数为两端的区间,找其中取模的最大值。找最大值的过程可以二分或双指针。值域很小,也可以......
  • 牛客小白87题解A-G
    A小苯的石子游戏本题贪心模拟即可B小苯的排序疑惑考虑到最简单的操作把n-1个数排好,最后一个看能否有序。即:a[1]<=min(a[2],a[3],a[4]..,a[n])||a[n]>=max(a[1],a[2],a[3]....,a[n-1])满足条件,反之易得不可能C&D小苯的IDE括号问题本题考察题意理解,简单版本我们可以只关注逻......
  • 0217-0224校赛部分题解
    SMUWinter2024Round#3(Div.2)对于自己比较有价值的题目是D题https://codeforces.com/gym/102897/problem/D?mobile=trueJ题https://codeforces.com/gym/102897/problem/JK题https://codeforces.com/gym/102897/problem/KE题https://codeforces.com/gym/102897/prob......
  • 关于thrift python接口和java通信出现问题解决
    真的无语,搞了一个下午。使用thrift出现错误,先说一下遇到第一个错误,如下图:那时候代码是这叼样```if__name__=='__main__':handler=MessageServiceHandler()processor=MessageService.Processor(handler)transport=TSocket.TServerSocket(None,"9090"......
  • P3157 [CQOI2011] 动态逆序对 题解
    题目链接:动态逆序对常见经典题,理解一个数对逆序对贡献计算即可。对于一个数而言,它在一个序列中的逆序对有两部分贡献,一部分为前面比它严格大的数,另一部分为后面比它严格小的数,有道二莫题也是基于此去考虑的。考虑最开始知道了总逆序数,每次删除一个数逆序数会减少两部分值,显然就......
  • 选课 题解
    题目描述大学里实行学分。每门课程都有一定的学分,学生只要选修了这门课并考核通过就能获得相应的学分。学生最后的学分是他选修的各门课的学分的总和。每个学生都要选择规定数量的课程。其中有些课程可以直接选修,有些课程需要一定的基础知识,必须在选了其它的一些课程的基础上才......
  • 洛谷 P4065 题解
    模拟赛T1,纪念一下第一次场切紫。(话说场上这么多人切是不是都找到原了,就我这么傻想了半天)正难则反,很容易的将题目转化为选择若干种颜色,使这些颜色在原数组中的位置连续。设$pre_i$为颜色$i$最早出现的位置,$suf_i$为颜色$i$最晚出现的位置。假设通过选择若干颜色得到的位......
  • P10149 [Ynoi1999] XM66F题解
    题解首先,问题是静态的区间查询问题,一眼莫队。那么我们就需要考虑所需要维护的内容在区间扩增或者缩减时的变化如何快速维护。我们可以先写出对于区间\([l,r]\)来说,满足\(l\lei<j<k\ler\)的有序三元组\((i,j,k)\)数量的表达式,方便拆式子:\[\sum\limits_{i=l}^{r}......
  • 启动vue-element-admin遇到问题解决方案
    概述从https://github.com/PanJiaChen/vue-element-admin下载代码,按照文档执行,期间遇到一些列问题。1#clonetheproject2gitclonehttps://github.com/PanJiaChen/vue-element-admin.git34#entertheprojectdirectory5cdvue-element-admin67#insta......
  • 出现8080端口占用问题解决
    查到占用端口号并关闭netstat-aon|findstr8080出现:TCP0.0.0.0:80000.0.0.0:0LISTENING23296TCP[::]:8000[::]:0LISTENING23296tasklist|findstr"23296"出现:java.exe......