dfs

莫队、带修莫队、树上莫队详解

人盡茶涼 提交于 2020-01-12 12:21:18
这几天学习了莫队算法,试着写一篇比较详细的莫队教程吧... 普通莫队 简介 莫队是一种基于分块思想的离线算法,用于解决区间问题,适用范围如下: 只有询问没有修改。 允许离线。 在已知询问 \([l,r]\) 答案的情况下可以 \(O(1)\) 得到 \([l,r-1],[l,r+1],[l-1,r],[l+1,r]\) 的答案。 满足以上三个条件就可以在 \(O(n\sqrt{m}+mlogm)\) 的时间复杂度下得到每个询问的解。 算法思想 莫队的精髓就在于通过对询问进行排序,并把询问的结果作为下一个询问求解的基础,使得暴力求解的复杂度得到保证。 上文中“适用范围”的第三点“ 在已知询问 \([l,r]\) 答案的情况下可以 \(O(1)\) 得到 \([l,r-1],[l,r+1],[l-1,r],[l+1,r]\) 的答案 ”即是“ 把询问的结果作为下一个询问求解的基础 ”的方法。 例: [国家集训队]小Z的袜子 在这题中,用 \(cnt_i\) 表示当前处理的区间内颜色为i的袜子出现的次数,用 \(\mathrm{len}\) 表示当前处理的区间的长度,用 \(x\) 表示新增的那只袜子的颜色。 以已知区间 \([l,r]\) 的答案求解区间 \([l,r+1]\) 为例。分别处理分子和分母: 分母为任选两只袜子的组合总数,原先是 \(\frac{\mathrm{len}*

DFS序详解

前提是你 提交于 2020-01-12 00:15:27
dfs序就是一棵树在dfs遍历时组成的节点序列. 它有这样一个特点:一棵子树的dfs序是一个区间. 下面是dfs序的基本代码: void dfs(int x,int pre,int d){//L,R表示一个子树的范围 L[x]=++tot; dep[x]=d; for(int i=0;i<e[x].size();i++){ int y=e[x][i]; if(y==pre)continue; dfs(y,x,d+1); } R[x]=tot; } 给定一颗树, 和每个节点的权值.下面有7个经典的关于dfs序的问题: 1. 对某个节点X权值加上一个数W, 查询某个子树X里所有点权的和. 由于X的子树在DFS序中是连续的一段, 只需要维护一个dfs序列,用树状数组实现:单点修改和区间查询. 2. 对节点X到Y的最短路上所有点权都加一个数W, 查询某个点的权值. 这个操作等价于a. 对X到根节点路径上所有点权加W b. 对Y到根节点路径上所有点权加W c. 对LCA(x, y)到根节点路径上所有点权值减W d. 对LCA(x,y)的父节点 fa(LCA(x, y))到根节点路径上所有权值减W 于是要进行四次这样从一个点到根节点的区间修改.将问题进一步简化, 进行一个点X到根节点的区间修改, 查询其他一点Y时,只有X在Y的子树内, X对Y的值才有贡献且贡献值为W.当单点更新X时

DFS 部分和问题

丶灬走出姿态 提交于 2020-01-11 23:33:36
给定整数 a1、a2、……、an,判断是否可以从中选出若干数,使它们的和恰好为k。 限制条件 1<=n<=20 -10^n<=ai<=10^8 -10^8<=k<=10^8 输入: n=4 a={1,2,4,7} k=13 输出: Yes (13 = 2 + 4 + 7) int a[MAX_N]; int n, k; // 已经从i项得到了和sum, 然后对于i项之后的进行分支 bool dfs(int i, int sum) { if(i == n) return sum == k; // 不加上a[i]的情况 if(dfs(i + 1, sum)) return true; // 加上a[i]的情况 if(dfs(i + 1, sum + a[i]) return true; return false; } void solve() { if(dfs(0, 0)) printf("Yes\n"); else printf("No\n"); } 来源: CSDN 作者: tmhhh 链接: https://blog.csdn.net/weixin_43569916/article/details/103939992

计蒜客 置换的玩笑(DFS)

倖福魔咒の 提交于 2020-01-11 02:37:49
传送门 题目大意: 小蒜头又调皮了。这一次,姐姐的实验报告惨遭毒手。 姐姐的实验报告上原本记录着从 1 到 n 的序列,任意两个数字间用空格间隔。但是“坑姐”的蒜头居然把数字间的空格都给删掉了,整个数字序列变成一个长度为 1 到 100 的且首部没有空格的数字串。 现在姐姐已经怒了,蒜头找你写个程序快点把试验数据复原。 输入 输入文件有一行,为一个字符串——被蒜头搞乱的实验数据。 字符串的长度在 1 到 100 之间。 输出 输出共一行,为姐姐的原始测试数据—— 1 到 n 的输出。 任意两个数据之间有一个空格。 如果有多组符合要求的正确解,输出其中任意一组即可。 本题答案不唯一,符合要求的答案均正确 样例输入 4111109876532 样例输出 4 1 11 10 9 8 7 6 5 3 2 解题思路: 因为字符串的长度不超过100,可以计算出n最大是54,我们只需要枚举一位数和两位数。 先通过字符串的长度计算出n,开一个数组标记枚举过的数,只有没标记过的数并且小于等于n才会存下来继续往后搜。 size<=9: n=size size>9: n=(size-9)/2+9 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h>

深搜的剪枝技巧

一个人想着一个人 提交于 2020-01-11 01:47:05
首先是深搜的模板: int ans = 最坏情况, now; // now为当前答案 void dfs(传入数值) { if (到达目的地) ans = 从当前解与已有解中选最优; for (遍历所有可能性) if (可行) { 进行操作; dfs(缩小规模); 撤回操作; } } 1.剪枝的概念: 实际上,对于搜索,其实就是一棵树: (树丑,莫要介意) 那么对于没有剪枝的dfs,需要搜索整棵树,而剪枝,就是将其中一部分枝干减掉,使时间复杂度降低。 2. 剪枝的原则:三个原则:正确性(这是剪枝优化的前提),准确性,高效性; 3.深搜的优化技巧: 优化搜索顺序 排除等效冗杂 记忆化 最优性剪枝 可行性剪枝 1.优化搜索顺序:不同的搜索顺序会产生不同的搜索树形态,其规模大小也相差甚远 2.排除等效冗杂:在搜索中,若我们发现沿某几条线路所达到的效果是一样的,那么我们可以只搜索其中的一条 3.记忆化:是啥?: 不依赖任何 外部变量 答案以返回值的形式存在,而不能以参数的形式存在(就是不能将 dfs 定义成 这里面的 nowans 不符合要求)。 对于相同一组参数,dfs 返回值总是相同的 模板: int g[MAXN]; //定义记忆化数组 int ans = 最坏情况, now; void dfs f(传入数值) { if (g[规模] != 无效数值) return; //或记录解

计蒜客 方程的解数(DFS)

浪子不回头ぞ 提交于 2020-01-10 02:35:55
问题描述 输出格式 输出一行,输出一个整数,表示方程的整数解的个数。 样例输入 3 100 1 2 -1 2 1 2 样例输出 104 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 const int INF=0x3f3f3f3f; 14 typedef long long LL; 15 const int mod=1e9+7; 16 const double PI = acos(-1); 17 const double eps =1e-8; 18 #define Bug cout<<"---------------------"<<endl 19 const int maxn=1e5+10; 20 using namespace std; 21 22 int k[5],p[5]; 23 int n,m,ans; 24 LL POW[150]

计蒜客 数独(DFS)

巧了我就是萌 提交于 2020-01-10 02:22:10
蒜头君今天突然开始还念童年了,想回忆回忆童年。他记得自己小时候,有一个很火的游戏叫做数独。便开始来了一局紧张而又刺激的高阶数独。蒜头君做完发现没有正解,不知道对不对? 不知道聪明的你能否给出一个标准答案? 标准数独是由一个给与了提示数字的 9*9 网格组成,我们只需将其空格填上数字,使得每一行,每一列以及每一个3*3 宫都没有重复的数字出现。 输入格式 一个9×9的数独,数字之间用空格隔开。*表示需要填写的数字。 输出格式 输出一个9×9的数独,把出入中的*替换成需要填写的数字即可。 本题答案不唯一,符合要求的答案均正确 样例输入 * 2 6 * * * * * * * * * 5 * 2 * * 4 * * * 1 * * * * 7 * 3 * * 2 * 1 8 * * * * 3 * 9 * * * * 5 4 * 1 * * 7 * 5 * * * * 1 * * * 6 * * 9 * 7 * * * * * * * * * 7 5 * 样例输出 1 2 6 7 3 4 5 9 8 3 7 8 5 9 2 6 1 4 4 9 5 1 6 8 2 3 7 7 3 9 4 2 5 1 8 6 8 6 1 3 7 9 4 2 5 2 5 4 8 1 6 3 7 9 5 4 7 2 8 1 9 6 3 6 1 3 9 5 7 8 4 2 9 8 2 6 4 3 7 5 1

祖孙询问

五迷三道 提交于 2020-01-09 16:54:32
题目描述 Description 已知一棵 \(n\) 个节点的有根树。有 \(m\) 个询问。每个询问给出了一对节点的编号 \(x\) 和 \(y\) ,询问x与y的祖孙关系。 输入描述 Input Description 输入第一行包括一个整数n表示节点个数。 接下来 \(n\) 行每行一对整数对 \(a\) 和 \(b\) 表示 \(a\) 和 \(b\) 之间有连边。如果 \(b\) 是 \(-1\) ,那么a就是树的根。 第 \(n+2\) 行是一个整数 \(m\) 表示询问个数。 接下来 \(m\) 行,每行两个正整数 \(x\) 和 \(y\) 。 输出描述 Output Description 对于每一个询问,输出1:如果 \(x\) 是 \(y\) 的祖先,输出2:如果 \(y\) 是 \(x\) 的祖先,否则输出 \(0\) 。 样例输入 Sample Input 10 234 -1 12 234 13 234 14 234 15 234 16 234 17 234 18 234 19 234 233 19 5 234 233 233 12 233 13 233 15 233 19 样例输出 Sample Output 1 0 0 0 2 数据范围及提示 Data Size & Hint 数据范围:对于30%的数据, \(n,m≤1000\) ,对于100%的

祖孙询问

我的梦境 提交于 2020-01-06 04:02:30
题目描述 Description 已知一棵 \(n\) 个节点的有根树。有 \(m\) 个询问。每个询问给出了一对节点的编号 \(x\) 和 \(y\) ,询问x与y的祖孙关系。 输入描述 Input Description 输入第一行包括一个整数n表示节点个数。 接下来 \(n\) 行每行一对整数对 \(a\) 和 \(b\) 表示 \(a\) 和 \(b\) 之间有连边。如果 \(b\) 是 \(-1\) ,那么a就是树的根。 第 \(n+2\) 行是一个整数 \(m\) 表示询问个数。 接下来 \(m\) 行,每行两个正整数 \(x\) 和 \(y\) 。 输出描述 Output Description 对于每一个询问,输出1:如果 \(x\) 是 \(y\) 的祖先,输出2:如果 \(y\) 是 \(x\) 的祖先,否则输出 \(0\) 。 样例输入 Sample Input 10 234 -1 12 234 13 234 14 234 15 234 16 234 17 234 18 234 19 234 233 19 5 234 233 233 12 233 13 233 15 233 19 样例输出 Sample Output 1 0 0 0 2 数据范围及提示 Data Size & Hint 数据范围:对于30%的数据, \(n,m≤1000\) ,对于100%的

[LeetCode] 1254、统计封闭岛屿的数目

让人想犯罪 __ 提交于 2020-01-04 00:03:51
题目描述 如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「 封闭岛屿 」(每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 ))。请返回封闭岛屿的数目。 输入:grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0], [1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]] 输出:2 解释:灰色区域的岛屿是封闭岛屿,因为这座岛屿完全被水域包围(即被 1 区域包围)。 解题思路 回溯经典题目:39、40、46、47、51、52等。本题和第1020题类似,普通的“ DFS着色法 ”就可以啦。本题和最普通的“数岛屿个数”(leetcode 200)的区别只是要求封闭,所以只需要代入一个变量表示岛屿是否封闭就可以啦。我的实现。 一题看透 DFS 和 DFS :DFS 和 BFS 都是常用来遍历搜索树或图的算法。二叉树中的前序、中序和后序遍历都属于DFS,层次遍历属于BFS。DFS常用递归和栈来实现,BFS常用队列来实现。 解题思路如下:每次遇到陆地则DFS。对该过程进行判断:如果途中丝毫不经过“边界”,则这就算作1个封闭岛屿;如果经过“边界”,则不算。 题目要我们求出封闭岛屿的个数,那我们可以先遍历矩阵中的每一个位置,如果当前位置为0(陆地)