08 2020 档案

摘要:虽然是块,但是其实可以看作是除了两边的两块外,中间做一下kmp算法 但是有几个坑点: 1.相同的数字要合并,因为相同的数字代表的其实是同一种,如果不合并,在匹配的时候看上去是不一样的 2.对于块数为1和2的直接特判一下就好 3.对于中间匹配的,也不要忘记判断一下两边的块是否合理 #include<b 阅读全文
posted @ 2020-08-31 22:28 朝暮不思 阅读(225) 评论(0) 推荐(0)
摘要:这道题算法很好想,为了不枚举每一个点做一遍,因此考虑换根dp,也就是先正的做一遍,之后从上面来更新下面的节点,难点在于细节非常复杂。 首先我们可以想到维护的是f[i][],g[i][],表示子树和上方的信息 分为f[i][0],和f[i][1]表示取完后回到i以及在i的某个子树中停留。 剩下的更新方 阅读全文
posted @ 2020-08-31 20:53 朝暮不思 阅读(199) 评论(0) 推荐(0)
摘要:仔细观察题目信息对做题帮助特别大。 本题一看数据范围不是很大,尤其是k很小,第一想法是能否把删除的边枚举出来每个做一遍 但是一算复杂度显然不太正确,题目当中重要的信息是,边权随机,这启发着我们最短路上的边数不会很多。 并且我们的目标是把最短路变长,因此显然我们要删除最短路的边,重复k次这样的操作就能 阅读全文
posted @ 2020-08-30 22:55 朝暮不思 阅读(199) 评论(0) 推荐(0)
摘要:#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<ll,ll> pll; const int N=5e5+10; const 阅读全文
posted @ 2020-08-30 21:30 朝暮不思 阅读(131) 评论(0) 推荐(0)
摘要:题意:给定n组点,表示在t分钟,x处有人出现。询问最少有多少人 每个人都可以从任意地点朝任意方向出发,每分钟走一步。 题解: 对于这道题,初始可能有一个想法,将这点放在坐标轴上,有两种直线可以选取,一种是斜率为-1的,一种是斜率为1的 我们要用这两种直线来覆盖所有的点,问的是直线个数的最小值。如果光 阅读全文
posted @ 2020-08-30 15:57 朝暮不思 阅读(148) 评论(0) 推荐(0)
摘要:对于这一类的很多操作,每次操作计算答案的题目,大部分都是前后答案有关的,也就是改变了当前操作的影响。 对于本题来说,一个朴素的想法是,我们对于当前的改变答案,影响到的点不包括子树中的,以及点到根路径上的点 这样可以简单的想到,看上去非常像树状数组,这样可以快速求。但是这里有一个问题,因为我们每次修改 阅读全文
posted @ 2020-08-29 21:43 朝暮不思 阅读(287) 评论(0) 推荐(0)
摘要:挺有意思,主要是仔细观察这个数列和题目所给的信息,CF题目的解法经常就隐藏在题目信息和案例中 首先我们肯定是关注题目所给的merge的定义,发现首位是一个与其他不同的特殊信息。其实不难发现,如果一个数能成为某个小数组的开头来合并的话 在他后面的比他小的数,一定要跟他成为一个集合。否则不成立,因为如果 阅读全文
posted @ 2020-08-28 20:15 朝暮不思 阅读(253) 评论(0) 推荐(0)
摘要:合并显然可以想到使用双向链表,而对于如何找到最大值,可以用优先队列,两重排序。 有一些细节就是涉及到合并,合并完后需要将原有的两个状态删除,但是优先队列做不到,因此用set记录一下 #include<bits/stdc++.h> using namespace std; typedef long l 阅读全文
posted @ 2020-08-28 17:01 朝暮不思 阅读(278) 评论(0) 推荐(0)
摘要:答案具有连续性,每次的操作可能导致三个结果,+1,不变,-1 我们考虑操作,如果之前存在,那么之前变少的数量要+1,那么就要分是否答案+1 之后,我们考虑现在的贡献,也分两种情况考虑答案是否-1 #include<bits/stdc++.h> using namespace std; typedef 阅读全文
posted @ 2020-08-28 15:15 朝暮不思 阅读(230) 评论(0) 推荐(0)
摘要:显然我们发现,如果出现两个峰,中间必然有点没被全部的区间覆盖,就得出了答案 因此我们只需要正反求一下最长上升子序列即可 #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long l 阅读全文
posted @ 2020-08-28 11:26 朝暮不思 阅读(192) 评论(0) 推荐(0)
摘要:做这题细节比较多,要想清楚实际的含义 首先我们肯定是想着枚举看看把哪些提到最前面 对于这题我们发现我们要维护的有两种情况,一种是相减小于0,一种是相减大于0 因此我们分两种情况讨论,并且注意状态的变化,具体细节看代码注释 #include<bits/stdc++.h> using namespace 阅读全文
posted @ 2020-08-28 10:37 朝暮不思 阅读(188) 评论(0) 推荐(0)
摘要:算法比较明显,二维hash用map判断即可,因为数据很小,因此不用过多考虑优化 #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pai 阅读全文
posted @ 2020-08-27 21:44 朝暮不思 阅读(150) 评论(0) 推荐(0)
摘要:首先观察到答案具有二分性,因此考虑二分答案。 对于check函数,朴素的想法就是枚举每个长度为mid的区间查询 我们发现区间gcd就等于区间最小值,因此考虑维护区间最小值和区间gcd 可以使用线段树维护,但是我们发现区间gcd也能使用st表维护 因此直接用st表维护这两个 #include<bits 阅读全文
posted @ 2020-08-27 20:29 朝暮不思 阅读(88) 评论(0) 推荐(0)
摘要:最重要的是观察到一点,最优策略一定是走到最远不能走的地方在转弯 因为我们一旦转弯,就永远不能越过这条线,因为只能右转,其实就相当于一个蛇形 所以只需要暴力模拟即可 #include<bits/stdc++.h> using namespace std; typedef long long ll; t 阅读全文
posted @ 2020-08-27 16:37 朝暮不思 阅读(143) 评论(0) 推荐(0)
摘要:这道题目考察了对于数据结构模型的运用和对于题目信息的理解与反思 首先观察到的是k很大,因此普通的方法并不可行。 但是观察题目可以发现,当所有城市的数量都是相同的时候,一定是按照一个循环取模就能找到答案 现在的问题是如何度过到将所有城市都相等。 题目的要求是,先选个数小的,第二关键字是标号小的,想象一 阅读全文
posted @ 2020-08-27 09:49 朝暮不思 阅读(170) 评论(0) 推荐(0)
摘要:发现每个点的出度为1,也就是说路径总是固定的,有观察到k很大,显然是通过倍增算法进行维护 #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pai 阅读全文
posted @ 2020-08-26 17:28 朝暮不思 阅读(242) 评论(0) 推荐(0)
摘要:观察本题,我们发现,如果某些操作每次都更新到了某个位置,那么我们可以通过维护bitset来发现这个对于这个位置来说的可能最大值 而且答案就是所有位置取一下或。因为我们发现对于每个位置,bitset上为1的那些数一定可以取到最大值。 但是这样过于暴力,我们发现这是一个区间操作,而区间操作一般和线段树相 阅读全文
posted @ 2020-08-26 15:15 朝暮不思 阅读(200) 评论(0) 推荐(0)
摘要:显然最终的答案是一个不降序列,因为一旦有下降,一定可以将两段合并,这样字典序更小 那么其实就是不断维护加入的过程,刚开始是一个数字一段,一旦前面的平均值大于等于准备插入的,那么就一定要合并,因为这样才能使最后的答案为不降序列 #include<bits/stdc++.h> using namespa 阅读全文
posted @ 2020-08-25 21:58 朝暮不思 阅读(194) 评论(0) 推荐(0)
摘要:最小斯坦纳树用于处理联通集合中指定的点的最小代价,一般来说可以通过其他不属于集合的点 最小生成树是特殊的斯坦纳树,它适用于联通集合中的所有点。 对于斯坦纳树,从两方面考虑他,首先我们定义f[i][s]表示以i为根,联通状态为s的情况 对于更新,从两个方面考虑,第一个方面,根不变,枚举子集更新当前状态 阅读全文
posted @ 2020-08-24 22:01 朝暮不思 阅读(191) 评论(0) 推荐(0)
摘要:对于本题,要发现的一点是,因为0,1各代表一个字符串,因此我们可以暴力枚举0代表的是什么,1代表的是什么,一个是前缀,另一个受前一个控制。 对于判断两个子串是否相等,可以使用哈希,这里我采用的是后缀数组求lcp,只要比较一下是否大于等于我们枚举的长度即可。 最后我们要判断一下0和1代表的东西不能够相 阅读全文
posted @ 2020-08-24 17:57 朝暮不思 阅读(165) 评论(0) 推荐(0)
摘要:观察到这个数据范围,显然不可能真的存这么大的邻接矩阵。 进一步发现,题目要求正方形矩阵的边长为偶数,并且里面的1为奇数 这启发了我们,因为边长为4的一定要用边长为2的拼接起来,这样边长为4的里面一定是偶数个1 因此直接特判掉n>=4的答案 剩下只有n==2,和n==3。 对于n==2,我们发现因为每 阅读全文
posted @ 2020-08-24 11:31 朝暮不思 阅读(195) 评论(0) 推荐(0)
摘要:显然,我们先按x排序,之后其实很容易发现答案就是从后往前遍历在i后面每个满足距离条件的j的答案再加上之间的距离, 也就是f[j]+j-i,如果枚举二维,那么就会超时,我们发现这个其实就是取max,可以用线段树维护,但是我们进一步发现,对于i和i之前的,目前还没有算出来,因此直接使用树状数组也可以维护 阅读全文
posted @ 2020-08-23 22:52 朝暮不思 阅读(183) 评论(0) 推荐(0)
摘要:可持久化并查集模板(启发式合并) #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,pll> plll; const int N 阅读全文
posted @ 2020-08-23 20:51 朝暮不思 阅读(159) 评论(0) 推荐(0)
摘要:#include <bits/stdc++.h> #define INF (1<<25) #define MAXN 200005 #define getSZ(p) (p?p->sz:0) #define getSUM(p) (p?p->sum:0) using namespace std; type 阅读全文
posted @ 2020-08-23 19:40 朝暮不思 阅读(103) 评论(0) 推荐(0)
摘要:主要是思想是对顶堆,将最大的雷电法术的放入加强集合,其他放入普通集合 之后维护两种法术的集合大小,因为每次操作最多只会将大小与真正的大小差1,因此判断更新即可 具体注释看代码,细节比较多,主要是注意判断集合是否非空 #include<bits/stdc++.h> using namespace st 阅读全文
posted @ 2020-08-23 15:22 朝暮不思 阅读(186) 评论(0) 推荐(0)
摘要:线段树维护区间取反和区间覆盖操作。 注意他们的优先级。 #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,pll> plll; 阅读全文
posted @ 2020-08-23 09:52 朝暮不思 阅读(144) 评论(0) 推荐(0)
摘要:字典树的裸题,插入删除很简单,对于查询,只要进行分类讨论,先计算合法方案,然后使得相异或的答案永远和l保持一致即可 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=3e6+10; int c 阅读全文
posted @ 2020-08-21 23:16 朝暮不思 阅读(144) 评论(0) 推荐(0)
摘要:显然,对于一个点确定了,那么整棵树都确定了,因此我们枚举每个点作为不变点 之后用f[i]表示该节点固定时答案是多少,这样就能跑出正确答案了 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1 阅读全文
posted @ 2020-08-21 20:44 朝暮不思 阅读(90) 评论(0) 推荐(0)
摘要:#include<iostream> #include<algorithm> #include<string> #include<cstring> #include<cstdio> #include<queue> using namespace std; typedef pair<int,int> 阅读全文
posted @ 2020-08-21 19:30 朝暮不思 阅读(144) 评论(0) 推荐(0)
摘要:由题意可知,可以分别统计以i为根的子树距离mod3的情况,并记录个数,之后用点分治可以使复杂度降到nlogn #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=3e5+10; const in 阅读全文
posted @ 2020-08-21 18:36 朝暮不思 阅读(128) 评论(0) 推荐(0)
摘要:二分最小值,能选第一个尽量选,之后选第二个看看能否满足答案 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=3e5+10; const int mod=1e7+7; int n,m,k; s 阅读全文
posted @ 2020-08-21 16:06 朝暮不思 阅读(123) 评论(0) 推荐(0)
摘要:这题只需要记录到当前位,之前总共有多少个1即可 因为首先这满足记忆化的条件,也就是可以在计算过的情况下直接范围答案 其次,我们现在需要理解的是,当我们计算出了这个之后,答案是可以直接累乘的 因为在某个数之后计算的所有数,最大值不超过他,也就是他这位所管辖的所有答案。 所以我们可以想到,这样其实就是把 阅读全文
posted @ 2020-08-20 23:16 朝暮不思 阅读(104) 评论(0) 推荐(0)
摘要:数字太大,找找规律比较好。 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; const int mod=1e9+7; int main(){ ios::sync_with_s 阅读全文
posted @ 2020-08-20 21:43 朝暮不思 阅读(117) 评论(0) 推荐(0)
摘要:这道题我们首先发现因为最多就一个地方不一样,因此其实最终的答案就是n+1个字符串所产生的,也就是对于给定串,只改一位以及原串加入字典树 之后的做法和一道经典例题(文本打印机)一毛一样,就是枚举在哪个节点跑ac自动机+dp #include<bits/stdc++.h> using namespace 阅读全文
posted @ 2020-08-20 20:40 朝暮不思 阅读(171) 评论(0) 推荐(0)
摘要:本来想对行列都维护线段树,然后每次查询两棵的最大值,之后进行修改。但是要考虑很多问题,例如最大值相同的时候选哪个,这些细节操作起来十分复杂,我也不知道是否可行 有一种巧妙的思路,我们发现取行对于取其他行没有影响,只对当前行有影响。因此就是用优先队列来分别计算选i次行,i次列的答案。 之后枚举选行的次 阅读全文
posted @ 2020-08-20 11:25 朝暮不思 阅读(110) 评论(0) 推荐(0)
摘要:首先约束不成立情况,因为他是最大值减最小值,所以对于成立的h来说,h1等于0,h[n]=n-1,并且h[i]>=h[i-1]。 其次我们需要计算的是合法的排列。对于h[i]>h[i-1],显然a[i]是当前的最大值或者最小值,因此答案值*2,并且多出了h[i]-h[i-1]-1个空位,这个空位的意思 阅读全文
posted @ 2020-08-19 23:14 朝暮不思 阅读(490) 评论(0) 推荐(2)
摘要:这道题如果暴力的话是平方级别的,然后我们可以看出来,显然能够使用换根dp来做 只需要维护做两边dfs,分别维护向上向下的答案即可,不但要维护距离,也要维护点数。 维护的时候都是维护mod3状态下的答案 #include<bits/stdc++.h> using namespace std; type 阅读全文
posted @ 2020-08-19 16:34 朝暮不思 阅读(204) 评论(0) 推荐(0)
摘要:换根dp裸题,换根其实就是先做一遍dfs后,重新做一遍,第一次用下面的更新上面,第二次用上面的更新下面 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+10; const int i 阅读全文
posted @ 2020-08-19 14:13 朝暮不思 阅读(115) 评论(0) 推荐(0)
摘要:首先,如果k可以,那么2*k一定可以,因为这是两个k合并而来,因此如果存在答案,那么在n/2+1中一定存在答案 对于x分为两种,当x>=0,那么f[n]是最优的,只需要判断一下他即可 对于x<0我们可以尝试枚举k,首先从最大开始往下,因为k每减小一位,意味着出现了一段前缀和,以及之前的最小值减去x。 阅读全文
posted @ 2020-08-19 10:24 朝暮不思 阅读(170) 评论(0) 推荐(0)
摘要:首先这道题他要求以最优的方法,那么显然我们发现,因为路可以随便走,我们从1开始,首先肯定可以取完与他连通的candy。 之后我们可以选择去哪个怪物房,因为我们只能用一次传送门,因此其实只能另外再取另一个连通块,并且必须要通过和1这个块相连的怪物房。 对于一个怪物房,我们随机进入一个邻边,只是一个简单 阅读全文
posted @ 2020-08-18 14:18 朝暮不思 阅读(137) 评论(0) 推荐(0)
摘要:首先根据题目所给的图片,我们其实可以发现,答案就是枚举每个点,以这个点作为中间节点的答案 这也就是意味着,我们刚开始按权值大小从大到小连边,答案就是入度*出度。而对于每次修改,就是去除这个点的贡献,同时修改他旁边点的贡献 这样能够保证复杂度的原因是,一旦我这个点被清空了,那么连边就没了。即使我们每次 阅读全文
posted @ 2020-08-17 20:23 朝暮不思 阅读(152) 评论(0) 推荐(0)
摘要:本题数据范围很小,因此直接根据右侧爆搜左侧选择哪个,再加上一个可行性剪枝就行 #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int inf=0x3 阅读全文
posted @ 2020-08-17 15:51 朝暮不思 阅读(400) 评论(0) 推荐(0)
摘要:设计dp状态为f[i]表示以i为根的子树能到达正确答案的概率是多少,那么f[1]就是答案 当我们先行计算出他儿子的答案时,根据独立性以及反方向考虑,我们只需要知道一次不能到达正确答案的概率,之后重复size遍,用1去减就是答案 #include<bits/stdc++.h> using namesp 阅读全文
posted @ 2020-08-17 09:53 朝暮不思 阅读(139) 评论(0) 推荐(0)
摘要:首先要抽象出模型,我们其实只需要管自己选啥英雄就行,因为这是有限制的,其他的直接使用组合数计算之后乘上就行 对于自己选的英雄,有5层,每层100个,最朴素的想法是枚举每人选什么,但是5层for循环超时了,但是4层for循环就很合理 因此我们只枚举前4层,之后看看第五层还能选啥就行。 #include 阅读全文
posted @ 2020-08-16 13:26 朝暮不思 阅读(242) 评论(0) 推荐(0)
摘要:对于本题,可以发现是一种bfs不断向外扩展的情况,也就是当某个点周围所有比他小1的点都更新过他了,那么他才可以更新别人,这里就有一种拓扑排序的思想 又因为题目告诉我们要找最长的,因此我们最后的答案某点,不能向外扩展,因此可以维护出度和入度,以入度为更新标准,以出度为是否能作为答案 之后拓扑时直接修改 阅读全文
posted @ 2020-08-16 10:17 朝暮不思 阅读(247) 评论(0) 推荐(0)
摘要:对于这题,我们发现1和3点是同类点,因此其实就是二分图染色,如果只有一个连通块,那么判断一下是否是二分图就行。 现在有多个连通块,因此我们还要判定一下能否把这些2分给这么多个连通块 因此可以做一下背包,先存一下每个连通图的信息,之后dp,除了维护可达性,还要维护一个把图的哪部分分给2 如果最后不能分 阅读全文
posted @ 2020-08-15 17:24 朝暮不思 阅读(145) 评论(0) 推荐(0)
摘要:这道题的状态可以设计为f[i][j]表示在以i为根的子树上,深度最小为j的最大值。这个深度是相对于子树的深度 因此我们枚举深度去更新当前子树答案,在第一次更新的时候,先去求深度恰好为j的答案,之后倒序取一遍max就是答案 如果深度为0,就是选择根节点,那么只要把所有子树中>=k的位置选进来就行(这里 阅读全文
posted @ 2020-08-14 10:55 朝暮不思 阅读(274) 评论(0) 推荐(0)
摘要:分块预处理,表示f[][],第i块到第j个数的答案 这样做的时候就可以大块直接查询,小块暴力查询 #include<bits/stdc++.h> #define getsz(p) (p?p->sz:0) using namespace std; typedef long long ll; typed 阅读全文
posted @ 2020-08-12 20:03 朝暮不思 阅读(146) 评论(0) 推荐(0)
摘要:这里必须要全部存图而不能直接判断原先最短路和给定特殊边的关系 因为我们如果用了某个特殊边,其实会影响到其他点最短路,使得他的最短路更小,我们直接判断,会导致本身的可以被删掉的答案,因为没用特殊边而不能删掉 所以本题的做法是,全部存下来后,记录某个点的最短路的个数 如果特殊边大于最短路,那就直接删掉 阅读全文
posted @ 2020-08-12 14:53 朝暮不思 阅读(190) 评论(0) 推荐(0)
摘要:这道题需要做一下模型转换,首先我们发现给定的边其实构成一个补图 如果我们暴力做这道题,那么就是遍历所有点,限制题目的边这样做收到了点的个数的制约 而我们可以这样想,我们把给点的边构图,那么其实就是求取他的补图的连通性 这里有一个好的发现就是,对于原来复杂度超时的代码来说,肯定是点数太多,才会超时,但 阅读全文
posted @ 2020-08-12 10:58 朝暮不思 阅读(146) 评论(0) 推荐(0)
摘要:设计二维dp状态为f[][],处理到i,比原来方案多j的答案是多少 这样可以根据h[i]和h[i+1]来作比较得到 这里因为多j个可能是负的,也就是当前答案不一定是正的,因此我们考虑坐标平移2001个位置,把2001这个点当作原点,这样不会产生边界情况 #include<bits/stdc++.h> 阅读全文
posted @ 2020-08-11 23:10 朝暮不思 阅读(167) 评论(0) 推荐(0)
摘要:这题我们显然可以发现,一个点越被迟处理越优,因此可以先预处理一波,接下来我们发现,如果贪心的在某个点最后可以取的位置去掉,那么可能会出现到后来不够的情况 因此其实我们可以使用反悔贪心的思路,先都取掉,用优先队列维护之前取掉的贡献值,从小到大排序 如果不够了,就把最小的那个去掉,这样兵力就能+1,因此 阅读全文
posted @ 2020-08-11 11:43 朝暮不思 阅读(178) 评论(0) 推荐(0)
摘要:建立超级原点,将边权设为票价,其他普通边权*2 做一遍最短路即可 #include<bits/stdc++.h> #define getsz(p) (p?p->sz:0) using namespace std; typedef long long ll; typedef pair<ll,int> 阅读全文
posted @ 2020-08-10 22:23 朝暮不思 阅读(149) 评论(0) 推荐(0)
摘要:对于自己控制和风向两种情况,我们可以发现,其实这两个是不冲突的 也就是对于风向我们是必须走的,而对于自己控制的肯定是朝最理想的状态 因此我们可以先把风向的贡献做出来,来二分天数,看看能否控制曼哈顿距离小于等于天数。 单调性的证明是,如果不可以满足条件,那么更小的天数也一定无法满足条件,因为我是最有利 阅读全文
posted @ 2020-08-10 11:03 朝暮不思 阅读(163) 评论(0) 推荐(0)
摘要:设计dp状态为f[i][0],表示以i为根的子树中,没有节点个数大于k的 和f[i][1]表示以i为根的子树中,最多有一个大于k 之后用树形dp来做答案,这道题标程的解答写的很详细 #include<bits/stdc++.h> using namespace std; typedef long l 阅读全文
posted @ 2020-08-09 17:40 朝暮不思 阅读(168) 评论(0) 推荐(0)
摘要:这题直觉上来说可以使用区间dp进行合法状态的转移,然后记录最小值。 现在的问题是这个是个无限长度的串,因此我们可以大胆猜测,只需要其中一部分就能把所有的情况构造出来 经过打表处理后发现,只需要前13个以内就能构造出所有合法状态,因此只需要这样区间dp即可 #include<bits/stdc++.h 阅读全文
posted @ 2020-08-07 11:11 朝暮不思 阅读(343) 评论(0) 推荐(0)
摘要:这道题的边权是2的幂次,显然我们发现边权前面所有边相加都不如这条边长,因此其实本题的最短路径就是最小生成树 之后对于答案只需要计算每条边的贡献即可 #include<bits/stdc++.h> #define getsz(p) (p?p->sz:0) using namespace std; ty 阅读全文
posted @ 2020-08-07 09:38 朝暮不思 阅读(219) 评论(0) 推荐(0)
摘要:对于这一类转移次数很多的,肯定是考虑矩阵快速幂比较有效 对于状态设计,就是把有用的状态和常数放到状态矩阵中 然后构造出转移矩阵,对于本题因为p/n的答案不定,所以考虑整除分块后,分块求取答案 #include<bits/stdc++.h> #define getsz(p) (p?p->sz:0) u 阅读全文
posted @ 2020-08-06 19:31 朝暮不思 阅读(130) 评论(0) 推荐(0)
摘要:这题设计二维状态f[][]表示前i个里面有几个0,假设数列中总共有cnt个0最后答案就是操作k次后前i个里面有cnt个0/所有情况 因为k十分巨大,所以考虑使用矩阵快速幂加速dp 对于矩阵状态的设计,就是看看转移状态,发现转移状态只是一个常数,因此列出矩阵后做一遍快速幂即可 #include<bit 阅读全文
posted @ 2020-08-06 11:20 朝暮不思 阅读(155) 评论(0) 推荐(0)
摘要:考虑每个点的贡献,每个点能够成为联通区块的左端点的个数就是他能给答案带来的贡献 如果a[i-1]>a[i],那么根据乘法原理贡献为(a[i])*(a[i-1]-a[i]) 如果a[i-1]<a[i],那么根据乘法原理贡献为(a[i]-a[i-1])*(n-a[i]+1) #include<bits/ 阅读全文
posted @ 2020-08-05 10:11 朝暮不思 阅读(117) 评论(0) 推荐(0)
摘要:只是转化成树上问题, 同样是动态开点维护 #include<bits/stdc++.h> #define getsz(p) (p?p->sz:0) #define getlsz(p) (p?getsz(p->ls):0) #define getl(p) (p?p->ls:0) #define get 阅读全文
posted @ 2020-08-04 22:11 朝暮不思 阅读(130) 评论(0) 推荐(0)
摘要:这道题我们发现固定一个端点,那么和他不同的或值答案就是不超过log个,因为就算每个只少一个0,那也只有20位 现在的问题是如何去重,采用的方法是对于每个右端点,用mp查找与他或起来的不同值,绑定一个三元组表示或值为u的键值对为i,j,这里我们可以覆盖掉一些被包含的点,因为不可能成为答案 之后继续去重 阅读全文
posted @ 2020-08-03 23:21 朝暮不思 阅读(235) 评论(0) 推荐(0)
摘要:#include<bits/stdc++.h> #define getsize(p) (p?p->sz:0) using namespace std; typedef long long ll; const int N=2e5+10; struct node{ int l,r; int sz; no 阅读全文
posted @ 2020-08-03 10:53 朝暮不思 阅读(126) 评论(0) 推荐(0)
摘要:本题最朴素的想法就是对于每个操作,都把他存起来之后查询的时候枚举一下 虽然这是超时的,但是有一个地方可以借鉴一下,那就是题目中的递推式我们在修改操作的时候,是通过经典的方法也就是w-depth[x]-depth[y]+2*depth[lca(x,y)]这个式子 我们猜想对于这种题,查询的时候不能线性 阅读全文
posted @ 2020-08-02 22:10 朝暮不思 阅读(282) 评论(0) 推荐(0)
摘要:套路题,经典dp枚举当前在哪个节点 #include<bits/stdc++.h> #define rep(i,x,n) for(int i=x;i<=n;i++) using namespace std; typedef long long ll; typedef pair<int,ll> pll 阅读全文
posted @ 2020-08-02 11:48 朝暮不思 阅读(144) 评论(0) 推荐(0)
摘要:这题如果普通数位dp,状态不好表示,但是我们发现,一旦当dp过程中,脱离了被最高项束缚的状态后,后面的数字就可以随便填 因此我们直接用组合数dp计算,首先维护前面出现的数字的个数,之后枚举答案d出现的合法状态的次数 设计dp[][],表示前i位,不包括d,在剩余的个数中已经存了j的答案。因此我们可以 阅读全文
posted @ 2020-08-01 22:21 朝暮不思 阅读(341) 评论(0) 推荐(0)
摘要:本题观察数据量非常小,并且求的是多串匹配,因此可以考虑使用ac自动机 设计dp状态为f[][],表示c中前i个字符匹配到第j个节点所能达到的最大值。 首先我们知道,两个匹配串在结束位置的点分别是+-1,而所有前缀能包含这两个字符串的,也应该设为对应的数值,对fail树进行修改进行。 dp的时候,枚举 阅读全文
posted @ 2020-08-01 10:20 朝暮不思 阅读(216) 评论(0) 推荐(0)