单源最短路径 使用“堆优化的”dijkstra 算法,每次对刚刚加入的点进行一次拓展,然后找出 dis 里面最大的一个。 时间复杂度:\(O((|V|+|E|) \log |V|)\),其中每一条边最多只会查找两次,优先队列的操作是每次 \(O(\log n)\) 的,一共 \(O(n\log n)\)。反正知道是 log 的就行。 板子: #includ
本题就是在一条1-n的路径上找p,q(先经过p),使得q-p最大。 考虑建正反图,正图上求出d[x],表示1-x的路径经过的节点最小值,反图上则从n开始求出f[x],x-n的最大值,最后枚举断点i,取最大的f[i]-d[i]就是答案。 基于动态规划的思想。 1 #include<bits/stdc++.h> 2 using namespace std; 3 con
易错点 测试点1、4:结点数量n和区块结点数k满足(n-1)%k==0的情况 测试点2:k为1的情况 如输入为:“00100 2 1 00100 1 12309 12309 2 -1” 代码 #include <iostream> #include <cstdio> #include <string> using namespace std; int a[100001]; string nxt[100001]; string p[100001];
代码 #include <iostream> #include <cstdio> #include <string> using namespace std; int a[100000]; string nxt[100000]; string p1[100000]; string p2[100000]; int main() { string addr1,addr2; int n; string address,naddress; int data; st
这题有一些前置知识:有源汇有上下界最大流。 首先,如果\(r<b\),那么我们希望\(r\)更多;否则我们希望\(b\)更多。其实如果\(r<b\),那么我们可以将\(r\)看成\(1\),\(b\)看成\(0\),目标是那么我们相当于将贡献从\(r\)和\(b\)变成了\(0\)和\(1\)。 那么考虑一个有上下界的最大流: 我们对于每行
原题链接 https://atcoder.jp/contests/arc142/tasks/arc142_d 对我来说,这是一道很复杂的 \(dp\) 题,很考验基本功,也十分考验分析问题的准确性。 考场上我的大致思路已经大差不差了,但是 \(dp\) 转移的细节实在是过于冗杂,导致我经过了一个月才把这道题目搞定,其中经历了各种没有考虑
P3375 这里字符串以 \(0\) 开始。 #include<bits/stdc++.h> using namespace std; #define f(i, a, b) for(int i = (a); i <= (b); i++) #define cl(i, n) i.clear(),i.resize(n); #define endl '\n' typedef long long ll; typedef unsigned long long ull; ty
link 题意简述:给定两个串 \(s,t\),求至少用 \(s\) 的几个前缀才能拼出 \(t\)。\(|s|,|t| \leq 1e5\)。 考虑 dp。设 \(dp_i\) 表示至少用 \(s\) 的几个前缀才能拼出 \(t\) 的前 \(i\) 个字符。转移方程:\(dp_i=dp_j+1 \ \text{if} \ t_{j,j+1 \cdots i} = s_{1,2,\cdots i-j}\)。这
C 把 \(a,b\) 全拆开然后比较即可(因为分裂和合并是互逆的) 注意开 long long . using namespace std; typedef long long ll; typedef pair<ll, ll> pii; int n, m, k; vector<pii> a, b, c, d; inline void solve() { a.clear(); b.clear(); c.clear(); d.clear(); scanf("%d%d
用两次dfs求出树的直径,这两次dfs可以写在一起,当然为了方便理解,这里是分开写的。 1 //两次dfs求树的重心 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 const int N=40005,M=40005*2; 8 int n,m,tot,p,ed; 9 int d[N],he
这道题考察了树的重心的性质,所有点到中心的距离之和是最小的,所以我们一遍dfs求出树的重心,在跑一次dfs统计距离之和。 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int INF=0x7f7f7f7f; 4 const int N=50005; 5 int head[N],to[N*2],nxt[N*2],f[N],size[N];
求树的重心的模板题,size[u]维护以u为根的子树大小,f[u]表示去掉u后的最大子树。 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int INF=0x7f7f7f7f; 6 const int N=20005; 7 int head[N],to[N*2],nxt[N*2],f[N],size[N];
题面,题解就不打了,写的较好的题解。 主要是借这个题说一下如何正确的思考出来一道题: 首先样例肯定要模,在模的时候就是构建思路的过程,当然一般的小样例无论什么方法都可以得出答案(spj),能过正确的理解题面就行; 然后我们就可以顺着方案A想,看看是否有漏洞(反例)、复杂度(以这个题来说:每个人
洛谷传送门 CF 传送门 思路 首先如果给出的位置合法(即不会有重叠部分不相同的情况),答案为 \(26^c\),\(c\) 为未填的字符数量。 于是本题的重点是判断是否有重叠部分不相同的情况。不难发现我们只用检验相邻的位置重叠部分是否相同。\(i \in [2,n]\),令 \(d = a_i - a_{i-1}\),只用判断
洛谷传送门 CF 传送门 思路 题意相当于将 \(S\) 表示成 \(A^kB\)(\(A^x = A^{x-1}A\),\(A^0\) 为空串),其中 \(B\) 为 \(A\) 的前缀。 考虑枚举 \(|A^k|\),设 \(|A^k| = len\ (k\ |\ len)\),在 \([1,len]\) 中寻找长度为 \(\dfrac{len}{k}\) 的循环节。看到循环节就想到 KMP,预处理出 \(f
洛谷传送门 CF 传送门 思路 首先求出原串的 \(\mathbf{Z}\) 函数数组 \(nxt\),那么长度为 \(n - i + 1\) 的前后缀满足要求当且仅当 \(i + nxt_i - 1 = n\)。 显然长度为 \(i\) 的前缀的出现次数为满足 \(nxt_j \ge i\) 的 \(j\) 的个数,差分 + 后缀和维护即可。 时间复杂度 \(O(|s|
假设你有n个大白兔奶糖,每次最多拿走一个或者两个,你有多少种不同的方法拿完全部的大白兔奶糖?(注意求解方法的时间复杂度) 输入描述: 大白兔奶糖的个数n (1<=n<=50) 输出描述: 拿完全部的大白兔奶糖的方法数 def numWays(n) -> int: cur, nxt = 1, 1 for _ in
题意: 定义 \(str^k\) 表示字符串 \(str\) 重复 \(k\) 次。 给定 \({s_1}^{k_1}\) 和 \(s_2^{k_2}\),求最大的整数 \(ans\) 使得 \((s_2^{k_2})^{ans}\) 是 \(s_1^{k_1}\) 的子序列 \(1\le |s_1|,|s_2|\le 100, 1\le k_1,k_2\le 1e7\) 思路: 有种比较直接的思路是模拟匹配的过程,每次
Uva11988破损的键盘 题目 有一个键盘,破了,在输入的时候会随机不间断的向文本中插入End和Home字符 (end:跳到待输入语句的末尾,在输入语句中用[表示;Home:跳到待输入语句的开头,用]表示)。 现请你编写程序,读入字符串,输出相应的结果。 分析 一种做法是采用vector,之后直接用insert函数,碰到
I 传送门 \(\texttt{Difficulty:1900}\) 题目大意: 一个长为 \(n(1\leq n\leq 10^5)\) 的序列 \(a(1\leq a_i\leq n)\) 。现在可以将该序列染色,染色方式由 \(01\) 序列 \(b\) 决定,将所有染成 \(0\) 的数字取出来,按原顺序排列得到序列 \(a^{(0)}\) ,由此也可得到 \(a^{(1)}\) 。定义
第一题 题意 数轴上有 \(n\) 条线段,你要在数轴上放点,使得每条线段至少包含一个点,最小化一条线段上最多放的点。 题解 神仙题。 首先有一个贪心想法,每次找到目前所有线段中最小的右端点,在这里放一个点,然后把包含了这个点的线段删掉,重复直到没有线段,设最后得到的答案为 \(K\)。 可以
AtCoder Beginner Contest 252 E - Road Reduction https://atcoder.jp/contests/abc252/editorial/4005 可以证明,总可以构建出一个生成树,使某一点到其余点的距离,等于原图中某一点到其余点的最小距离。 证明方法为,每次保留最小距离路径的最后一条边。 故可以使用dijkstra算法直接
题面 需要动态维护一个点集的极小联通子图边权和。可以发现,将点集 \(\{a_i\}\) 中的点按照 dfs 序从小到大排序之后,\(dist(a_1,a_2)+dist(a_2,a_3)+\ldots+dist(a_{k-1},a_k)+dist(a_k,a_1)\) 恰好等于我们要维护的那个边权和的两倍。所以就开一个 set,在加入和删除的时候加上或删
题面 本来就是个裸的KMP,但是这个题是有删除的,所以可以维护一个栈,每次的 \(j\) 都继承栈顶元素的 \(j\),然后如果找到了一个匹配,就直接弹栈即可。因为只会进栈 \(O(n)\) 次,所以总复杂度也是 \(O(n)\) 的。这个题算是栈的妙用了。 点击查看代码 #include<iostream> #include<cstdio>
题面 虽然 \(n,m\leq 5000\),但是这题是 \(O((n+m)|\Sigma|)\) 的。首先建 \(S\) 的 SAM,拿 \(T\) 上去跑可以得到 \(T\) 每个前缀的匹配区间(在 \(S\) 中只出现一次)。接着建 \(T\) 的 SAM,也可以求出每个前缀在 \(T\) 中只出现一次的区间。做一个区间交,取一个全局 \(\min\) 即可。