首先声明:此题不满足二分条件,一切写二分的题解均为误解 请注意辨明!
题目大意:给定一个m*n的洞穴矩阵,每个洞穴里面有若干地鼠,我们需要选定一个r*c的锤子进行击打,每次击打必须保证r*c的范围内所有洞穴均有地鼠,且每次击打只会打掉每个洞穴恰好一只地鼠,求最小击打次数
m,n<=100
考虑一个1*8的洞穴,当我们把锤子设作1*4时可以完成击打,而1*3不能 故不满足单调性,二分不正确
但是一个性质是确定的:假设我们选定一个3*4的锤子可以完成击打,那么我们选定一个3*2的锤子也一定能完成击打
那么反过来,当我们选择一个3*2的锤子无法完成击打时,那么3*4的锤子一定无法完成击打
说白了这题是一个偏是积性函数
于是这题我们选择线性筛进行筛选 若r相同时c1无法完成击打,那么c1*p也无法完成击打
验证的话 首先选定锤子时打的方案是一定的,于是我们贪心,从左上至右下依次击打,每个位置击打的次数等于击打区域左上角洞穴的当前地鼠数量,当击打后任意洞穴地鼠数量不为零
然后验证的时候强行模拟是O( (mn)^2 )树套树可以变成O( mn*logm*logn )
但是这道题有修改而没有查询(每次查询节点时前面必须为零) 故我们选择O(1)修改O(n^2)查询的二阶差分
向左向上进行两次差分 然后每次修改如图
击打后整个区域都为零则可以完成击打
此外这题O(n^4)暴力都能过 而且只比正解慢了四毫秒 就连O(n^6)的暴力加点剪枝都过了0.0 什么情况究竟
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 110
using namespace std;
i