04 2022 档案
摘要:一看就是哈希+dp 用到哈希是因为要看当前子串和原子串是否匹配 用dp是来统计方案数的 dp[i] 表示前i个字符的方案数 转移方程: 设原串的长度为len 如果匹配(哈希值相等) dp[i]=dp[i-1]+dp[i-len] 表示当前这个子串可以换成* 如果不匹配 dp[i]=dp[i-1];
阅读全文
摘要:一定要注意前提条件 !!!!gcd(a,p)=1 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long map<ll,int>mp; ll mod,b,n; ll ksm(
阅读全文
摘要:比赛的时候被前面的题目心态搞崩了 时间就不够了 就一个简单的拓扑排序 唉 真可惜了 首先对行字符串从前往后建边就好 对于上下两个具有相同前缀的字符串 首先必须两者大小相同 之后就对第一个不同的字符串建边就好 最后因为要字典序最小 用优先队列就好 #include <bits/stdc++.h> us
阅读全文
摘要:注意点 :重构树相连起来 只是保证存在一条路径 但是树上的路径不能保证最短 既然下车步行了 就不用再考虑海拔高度了 尽量走最少的路就行了 #include<iostream> #include<cmath> #include<algorithm> #include<queue> #include<c
阅读全文
摘要:首先这个题目正面模拟是不可能的 因为加入这个点后的改变值不好算 那就整体想 因为要到其他外卖点 所以有很多边是要走两遍的 一去一回 但是又不用再回到外卖站 不回到外卖站一定是到最远的那个 所以很清晰了 对于外卖站到每个外卖点覆盖的路径*2-最长的一条 #include <bits/stdc++.h>
阅读全文
摘要:这个题好啊 为什么会想到 K r u s k a l Kruskal 重构树呢? 我们最好情况一定是遍历完所有的点,那么最优路线一定是最小生成树 我们能否继续到达某个点很大一部分是根据最小生成树路径上权值最大的边 观察一波 K r u s k a l Kruskal 重构树的性质: 边权越大的形成的
阅读全文
摘要:首先肯定是先找到最大的ai为maxx 答案起码是maxx 发现如果我们按照从大到小依次摆放 只要maxx*(n-1)能容下Σai 那一定能满足(自行模拟一下就好,顺序一定是从大到小) 所以我们只要不断使maxx++ 直到maxx*(n-1)>=Σai就好 #include<bits/stdc++.h
阅读全文
摘要:就是一道树剖的裸题 实话说树剖细节挺多的 我打这个代码的时候遗漏的细节 1;有重儿子才先进行重儿子遍历 比如叶节点没有重儿子(默认为0) 是不能遍历的 不然会死循环 2;初始赋值的时候 是对1-n这有序的线段树进行赋值 所以有个rk[] 这个非常易错!!!! 出题人比较狡诈 样例能过 因为每个节点有
阅读全文
摘要:很明显可以用小根堆来处理 但是数据范围不允许 考虑线性想法 这个做法很好很实用 针对每次维护最小的且每次最多增加一个最小 都可以用这样的方法 !!!!完全可以替代小根堆 最后pufer转化为树反过来就好了 思路是一样的 #include<bits/stdc++.h> using namespace
阅读全文
摘要:题目大意 对选手编号有些大小的约束条件 最后求不同编号的最大数目 首先可以想到差分约束 最后答案就是求最最短路+1(最开始的点) 因为缩完点之后各个点之间一定是0连接 所以两边大小可以随便取 判断负环只需要判断dis[i][i]<0 即可 #include<bits/stdc++.h> using
阅读全文
摘要:又是一个差分约束的题 好像dp也能写 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<deque> #define Endl endl;//qwq using namespace s
阅读全文
摘要:不得不说人家省选题目出的就是有水平 开始一直没有搞懂题目到底什么意思 这句话是关键:只有结果保证惟一的选法才统计在内 也就是左边有很多种可能性 右边选出来有很多种可能性 必须是左边严格大于右边(可能性不相交)c1++ 同理 那这样就好理解了 因为是大小关系 想到差分约束 因为我们要严格大于或者小于
阅读全文
摘要:首先区间个数可以转化为前缀和的形式 然后就是差分约束了 最少包含多少个数 就是不等式为a>=b+c 的形式 只要满足了最长路的不等式 其他所有的不等式也都满足 就是跑一遍最长路 差分约束的关键在于这个约束 一定要把所有的限制条件找出来 这个题看似只有一个区间个数的限制 其实还有 每个数最多选一次(集
阅读全文
摘要:首先吐槽这次比赛题目描述真的太冗长了 单说这个题目还是很好的(尽管很简单) 首先不难想到最短路 肯定是从靠近源点到远离源点的顺序去走 每次走的下限可以不管 因为可以在一条路上来回走 因为要求每天多走一条新边 所以我们考虑每条边 如果这条边的其中一点乘2(保证来回)小于上限 那么肯定就有多的步伐走这条
阅读全文
摘要:我要是早点复习一下带权并查集 当时这个题就能A掉了 啊啊啊啊啊啊心态爆炸 这就是一个带权并查集的模板题啊 给出[l,r]的区间和,相当于s[r]-s[l] 一旦已经知道了 s[a]-s[b],s[b]-s[c],显然再给出一条[a,c]就可以判断"真假"了 将每条这样的信息(l,r,w),l,r放入
阅读全文
摘要:算是一个模板题吧 给出[l,r]的区间和,相当于s[r]-s[l] 一旦已经知道了 s[a]-s[b],s[b]-s[c],显然再给出一条[a,c]就可以判断"账本的真假"了 将每条这样的信息(l,r,w),l,r放入一个集合中, 用并查集来维护,并维护cha[l]=s[root]-s[l],cha
阅读全文
摘要:首先奇数肯定不行 构造如果都是1 一个1的价值为2 肯定是不够的 考虑尽可能构造0 如果是 10 那次数分别是 4 2 倒一下就是 2 4 如果是 100 那次数分别是 8 4 2 倒一下就是 2 4 8 所以尽可能接尽可能多的0 模拟一下就好 #include <bits/stdc++.h> us
阅读全文
摘要:首先能想到floyed暴力做法 60分是没问题的 进一步 两点之间路径可能会有多条 但是我们只用找到路径上最长边最小的那条 但是因为有多个询问 所以我们不能单方面考虑两个点 而是考虑很多对两个点 考虑建立最大生成树 这样的解一定是最优的!!!很巧妙 最后找两点之间的最短的那条边 用倍增lca 顺便维
阅读全文
摘要:先看道板子题 初始化 F1 F2 F3 进行n-1次加速以后 变成 Fn Fn+1 Fn+2 点击查看代码 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long const
阅读全文
摘要:预处理 nxt[i,j] 表示i到j最近距离i的下一个位置 最后记忆化搜索就好 #include<cstdio> #include<queue> #include<cstring> #include<iostream> using namespace std; int cur,n,m,s,t; in
阅读全文
摘要:不得不说这个树形dp做法真牛 题目大意:给出一棵树,求一条路径,选择路上的V个点,使得被选择的点的相邻且不在路径上的点的权值和最大。 考虑换根的话很麻烦 还是类似毛毛虫那个题 每个点一定是处于一个路径的中间的 可能是一上一下 一下一上 一下 一上这四种情况 因为这个题目是有方向性的 a->b 的权值
阅读全文
摘要:这个dp以前没见过 确实不会 怎么才能保证两两互不相交呢 在我印象里面没有这样操作过的dp 考虑换个想法 设dp[i,j,k]表示 前i个 两者差值为j 用了k次加倍 因为下标不能为负 所以整体向右偏移1300 初始化 dp[0,1300,0]=0 答案 max{dp[n,1300,i]} i属于[
阅读全文
摘要:树上计数 考虑如果一个点的亲儿子是偶数个 两两亲儿子配对就好 如果一个点的亲儿子是奇数个 挑一个出来和连上父亲 其余偶数个两两配对 n个两两配对的方案数为 (C(n,2)×C(n-2,2)×...×C(2,2))/((n/2)!) 化简得 (n!)/(2的n/2次方)×((n/2)!)预处理阶乘就好
阅读全文
摘要:穿插R和B乱搞一下就好 点击查看代码 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long const int maxn=105; char ans[maxn]; int
阅读全文
摘要:签到题 输出l 和2l即可 点击查看代码 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long int T; int main(){ cin>>T; while(T--){
阅读全文
摘要:当时比赛的时候期望不是多熟练 现在看来这个题还是多简单的 设E(k)表示当前在第k层 到n层期望的时间 当前有两种情况 要么到k+1层 要么回到0层 到k+1层: (1-p)× [E(k+1) + 1] 回到0层: p × [E(0)+1] E(k)=(1-p)× E(k+1) + 1 + p ×
阅读全文
摘要:天梯赛就是喜欢搞些复杂的dfs和bfs 这题就是一道三维的bfs #include<iostream> #include<queue> using namespace std; struct Node { int a,b,c; Node(int a1,int b1,int c1):a(a1),b(b
阅读全文
摘要:首先一看就知道是并查集 但是其实这个题不简单 首先要把题目读清楚 一个集合 a b c 可能a和b b和c分别有交集 但是a和c没有交集 首先可以想到对拥有同一个兴趣爱好的人合并 这样 a和b b和c 都分别合并了 现在考虑将 ab整体 和 bc整体 合并 每个人作为b 依次将每个人的兴趣爱好合并即
阅读全文
摘要:开始我想的是用multiset 和stack维护 但是发现 虽然multiset插入很方便 但是不能查询中值 这样就可以拿到17分了 查询中值最快的方法一定是数组下标 假如我们用数组代替multiset的话 唯一不方便的就是要让每次插入后序列都有序 每次排序肯定不行 考虑lower_bound操作
阅读全文
摘要:转移方程还是很容易想到 dp[i,j]=min(dp[i-1][j-1]+abs(),min(dp[i,j-1],dp[i-1,j])+1); 但是我写完之后发现答案就是不对 看完别人的code之后 才发现还要初始化!!!! 因为这个dp我们是对后面的字符进行操作 没有包含到在第一个字符串前加入很多
阅读全文
摘要:发现就是直线距离公式 所以排序之后 取左右两个端点就好 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long const int maxn=2e5; int T; stru
阅读全文
摘要:就是一道高中物理题 让一名高中生都会做 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long double w,p; int main(){ cin>>w>>p;w/=10
阅读全文
摘要:题目保证一定存在一条直线 假设这条直线不经过任何线段的端点 那么通过旋转或者平移 一定可以使得线段经过端点 那么只要固定一个端点 再判断斜率范围就好了 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #def
阅读全文
摘要:题目大意 给出锥形的表面积 求体积的最大值时 的体积 底面积 和高 很明显的一个单峰函数 三分法 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> const
阅读全文
摘要:考虑01背包 因为要求刚好凑满 所以转移的时候要判断一下 最后就是要求输出字典序最小的 首先保证能凑到 再者序列长度尽量长 最后保障小 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll l
阅读全文
摘要:很明显就是一道最短路问题 并且记录路径 还有一个坑点是 第一个输出的是最短路径数目 不是经过节点数目!!! 最后就是输出路径 我开始一直写成 pre[u]==mp[S]了 导致老是路径输出少一个 最后才发现错误 应该是u==mp[S] !!!! #include<bits/stdc++.h> usi
阅读全文
摘要:发现 只有末尾全是9才会增加递增序列 所以判断最后是否全部都是9 如果是 那就是所以位数之和 如果不是 那就是最高位-1加上其他位置上都为9的各个位数之和 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #d
阅读全文
摘要:考虑相邻的两个树的高度 算出相邻两个树高度满足题意的时间区间 最后对每个时间区间取并 如果交集不为0 则取交集最小的 如果交集为0 则不成立 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define l
阅读全文
摘要:很简单的一道dp 比赛的时候因为初始化的问题耗费了好多时间 dp[i]表示以i为结尾的连续字母的跨度 dp[i]=i-pre+dp[pre] 其中pre为i位置字母的前一个字母 最后答案就是min{dp['Z']} #include<bits/stdc++.h> using namespace st
阅读全文
摘要:因为只能选择一条边进行增长 我们选择最小的一条边进行增加 接着发现增加后的面积要么是单峰函数 要么是单调函数 所以运用三分法去解决 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll lon
阅读全文
摘要:设不同方案数为cnt p=1/cnt 1/p=cnt cnt=总方案数/重复的个数 这里就是一个简单的高中排列组合的知识 点击查看代码 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll l
阅读全文
摘要:根据题意很容易想到二分 但是问题来了 二分面积但是长宽还是需要O(n)来确定 完全承受不了 观察这个题目相较于一般的最大子矩阵问题 在于两个数列 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define
阅读全文
摘要:观察发现两个0之间至少有2个1才能满足题意 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long int T; vector<int>Q; int main(){ cin>
阅读全文
摘要:很容易想到dp dp[i,0]表示前i个 第i个不换 的最小值 dp[i,1]表示前i个 第i个换 的最小值 转移一下就行了 #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long l
阅读全文
摘要:简而言之: 一棵树,每秒钟你要做两个操作: 传播:对于每个顶点v,如果v的至少一个孩子被感染,你可以通过感染你选择的v的至多一个其他孩子来传播疾病。 注射:你可以选择任何一个健康的顶点,感染它。 求最少的次数 分析:很明显只关于一个节点儿子的个数为多少 如果有x个点有儿子 那么至少需要x次 并且很明
阅读全文
摘要:本来想练一手费用流的 但是一看这个题分层图跑的更快 而且也是个很好的分层图板子 将图分为k+1层 因为充满油可以跑k条边 算上 开始的1 就是k+1层 首先 第x层图中的点[i,j] 连向第x+1层的点[i,j]的 边权为 0 如果该点不是加油站 第x层[i,j] 连向第x+1层[i,j+1] [i
阅读全文
摘要:首先 具体有哪些点对我们是很好找到的 问题转化为 多次询问区间 有多少点对 对于多次区间离线询问 考虑定一边R 从左到右依次选择 对询问的R从小到大排序 这题树状数组还是很好想的 考虑一个点对【l,r】 一个询问【L,R】 如果r>R 那么这个区间一定不会考虑这个点对 所以有点对r<=R时才加入树状
阅读全文
摘要:离线询问最大完美数列长度 这种[L,R]的题目一般都先定R 然后再一个线性递推 设f[i] 表示第i个数为完美序列结尾 开头最大的位置 明显f[]是单调递增的 明显以i结尾完美序列的最大长度就是 i-pos+1 再考虑一个询问[L,R] 对于f[i]>L的情况 就相当于询问区间最大值 特别的 可能最
阅读全文
摘要:一道很早做过的题 其实很好感性理解 第一个数列的第k大 对应 第二个数列的第k大 那么问题就变为 用最少的步数 交换两个相邻的数 使得两数列一一对应 这就是一道逆序对的模板题 #include<bits/stdc++.h> using namespace std; #define lowbit(x)
阅读全文
摘要:这道题因为每个字符串长度很小 我们直接就分解每个字符串的子串 还是很基础的 如果数据开大一点难度又会上升一个阶段 这个题连用了三道STL map vector set #include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(
阅读全文
摘要:首先一看就知道是个小水题 出题人能不能准确描述 子串就是子串 什么叫连续子序列? 简而言之 找到一段颜色数量小于k且最长的子串 对每一个位置 维护一个pre数组 和endd数组 pre:在它前面离它最近的相同颜色的坐标 endd:在它后面离它最近相同颜色的坐标 初始L=R=1 不断地往后更新就好 #
阅读全文
摘要:经典的状压dp 先考虑横着放 如果横着放的方案确定了 那么竖着放的也就唯一确定了 所以总方案数=横着放的方案数 但是可能我们横着放完了后 留下的空间竖着放怎么都不能放满(也就是竖着连续对的0为奇数)不合法 这个我们可以预处理 定义方程:设dp[i,j]表示前i列已经放完横木块且第i列的状态为j的总方
阅读全文
摘要:题目大意: 一个数列(保证是个数是偶数),前一半之和 与 后一半之和 如果相等 就称这个数列为开心数列 但是数列有些数字被擦掉了为'?' 现在M和B两人玩游戏 M先手,每一轮将'?'填0到9的数字 最终数列如果为开心则B胜利 如果不开心则M胜利 M和B都很聪明 给出数列求最终胜利者 分析 ans1表
阅读全文
摘要:这个题几年之前做的时候就是不知道咋做 现在看起来就是一道简单的dp 首先枚举区间肯定是不行的 但是这个题目比较狡猾 数据范围给你2e5 迷惑你不往线性递推方面想 我开始想对每个点分析 分析他对答案会有什么贡献 以往有些题目就是这样的 但是发现没法分析 换个想法 考虑区间[L,R]固定R,依次dp就好
阅读全文
摘要:条形:P1031 [NOIP2002 提高组] 均分纸牌 ※第一堆牌相差的牌只能由第二堆牌承担(给予或索要) ※第一堆牌都达到要求了又去动它干嘛 ※可以直接删除第一堆牌 ※第二堆牌神奇的变成了第一堆牌 ※重复上述操作 ※如果当前牌没操作就已经达标了跳过啊~ ※下副牌变成负数又怎么样? ※ ∵ 上述步
阅读全文
摘要:很好的一道树形dp 具体哪些点选黑选白我们肯定是不知道的 但是题目最后要求的是求贡献 所以只要我们能算出贡献就好了 因为答案是线性的 简而言之就是 ∑每个边的贡献=总贡献 考虑一条边的贡献 边一侧的黑节点数另一侧的黑节点数边权+一侧的白节点数另一侧的白节点数边权 设dp[u,i]表示u子树选i个黑点
阅读全文
摘要:这个题知道是最大流 但是比赛的时候就是不知道怎么建图 #include <bits/stdc++.h> using namespace std; const int N = 1500, M = 10010, INF = 1e9; int n, m, S, T; struct Edge { int t
阅读全文
摘要:不消说 第一个问就是求最长不下降子序列 这个题的重点是第二个问 Dilworth定理:偏序集的最少反链划分数等于最长链的长度 简而言之就是要求最长上升子序列(严格上升的) 点击查看代码 #include<cstdio> #include<cstring> #include<algorithm> us
阅读全文
摘要:没啥说的枚举 这里用到stl里面的set 来保存每条直线的斜率和截距 点击查看代码 #include<bits/stdc++.h> using namespace std; struct point{ int x; //横坐标 int y; //纵坐标 }; int main(){ vector<p
阅读全文
摘要:今天WC的时候想起之前打比赛遇到一道挺有趣的题目 最后才做出来的 我们从上帝视角(就是站的很高很高)看士兵过河 每个士兵就好比是一个蚂蚁 两个蚂蚁相遇分别转向 就好比是两个蚂蚁一直直线行走 这样一个蚂蚁的时间就很好算 我们就能算出 所有蚂蚁的时间 但是a蚂蚁算出来的时间不一定是a蚂蚁走出河岸的时间
阅读全文
摘要:首先要把题目分析清楚 假如每个点作为根节点 所有叶节点到该根节点的路径权值和 除以 以该节点为根节点的叶节点个数 这个除以操作很烦 我们想办法先去掉 (一般这种除以什么的都要先乘上 最后再除) 所以我们先不考虑除以这个操作,因为以该节点为根节点的叶节点个数我们单独维护还是很好维护的-->cnt[]数
阅读全文
摘要:首先第一个是非常不划算的 所以我们想办法先将没有前缀的前放进去 第二就是第三的特殊情况 有公共后缀的一定是连在一起的 几堆不同公共后缀的 一定是先排数量小的一堆 因为这样对后面几堆产生的贡献最小 最后说白了就是先按照sz排序 最后按照dfs序走一遍dfs统计答案就好 #include<cstdio>
阅读全文
摘要:和之前那个题目很像 https://www.cnblogs.com/wzxbeliever/p/16087337.html 我想的是 先建立字典树 依次判断每个字符串 对于同一深度 只要满足该字符比其他字符前面就好 到这里都是没问题的 我开始想的是每层依次判断26个字母满不满足 于是开心的提交了 发
阅读全文
摘要:非常好的一道题!!!! 字典树上的dp题目 首先建立字典树 开始我理解错了 以为只要树上的1是连续的就满足 于是就打了个56分 树上的最大连续和 出题人还是比较好 这样的情况都有56分 实际情况是 就是从高到低再到高这个情况 问题很明显就变成了维护最大值和次大值(更新最大值的时候一定要先更新次大值)
阅读全文
摘要:这个题好难 真的好难 对拓扑排序不是很熟练 但是能明显感觉到强烈的先后顺序 但是就是建不了边 因为这个题要求最后的目标顺序 那我们就按照他的目标顺序进行插入字典树 这样的好处就是 已经在字典树里面同层的点一定是要在现在插入点前面出现的 前缀这个点太容易忽略了 不过题目还算良心 只有两个点有前缀 要是
阅读全文
摘要:字典树很好的一道题 这个题区别于一般的字典树前缀匹配在于 匹配的字符串可能比字典树上的长 也可能比字典树上的短 如果只是维护一个节点会被经过多少次肯定是没法解的 考虑再维护一个endd数组 表示以i节点为结尾的字符串数量 在查找的时候 比匹配字符串短的节点直接+endd数组即可 经过节点数sum就不
阅读全文