
洛谷
穷源溯流
路很长,尽管走便是。
-
原创 洛谷 P3674 小清新人渣的本愿(莫队 +bitset)
我们利用一个长度为 1e5 的 bitset,当数值 c 出现时,将 c 位置赋值为 1,对于题目要求的操作可以转变为求 bitset 中存在两个位置相差为 x 的 1 这个比较难,如下图 bitset 所示,假设 a+b=x,那么 x-b=a,所以将 N-b 向右移 N-x,即为 x-b,判断 x-b 是否等于 a 即可 枚举所有的因子,判断因子所在的位置是否都为 1const int N=1e5+5; int n,m; int i,j,k; ...2021-03-01 14:49:493
0
-
原创 洛谷 P4688 [Ynoi2016] 掉进兔子洞(莫队+bitset)
不难发现最后的答案为,其中 k 为三个区间内拥有相同元素的个数所以,只要能够求出 k 的值,题目便可迎刃而解由于将数据只有 1e5,所以利用一个长度为 1e5 的 bitset,将三个区间内每个区间中的元素在相应位置标 1(其余位置为 0),这样这三个 bitset 做与运算即可知道这三个区间共同含有的元素个数注意 :由于空间不允许开 1e5 个长度为 1e5 的 bitset,所以需要用时间来换取空间const int N=1e5+5;const int M=N/3+5;...2021-03-01 13:20:156
0
-
原创 洛谷 P4427 [BJOI2018]求和(树剖)
由于题目多次使用求幂在累加求和的过程,所以现预处理 3e5以内的 50 次方,利用树剖可以解决问题,但是学要注意的是,题目以 1 作为根节点,所以 1 的深度为 0const int N=3e5+5; int n,m; int i,j,k; //int a[N]; int dp[N][50+5]; vector<int> G[N]; struct Node { int l,r; ...2021-03-01 10:23:396
0
-
原创 洛谷 P2953 [USACO09OPEN]Cow Digit Game S(sg函数)
已知 1~9 处于必胜的状态,如果一个位置处于 P态(必败),那么他的下一个状态全为 N 态(必胜) 如果一个位置处于 N 态(必胜),那么他的下一个状态至少有一个 P 态(必败)预处理所有的状态即可const int N=1e6+5; int n,m; int i,j,k; int sg[N]; //bool vis[N];void getSG(){ for(int i=1;i<10;i++) sg[i]=1;...2021-02-28 11:27:0012
0
-
原创 洛谷 P2261 [CQOI2007]余数求和(整除分块)
利用整除分块可以解决后面的求和部分,但是需要注意:k!=n,若,则,所以 是的最终位置,其不可以超过 nll go(ll n){ return n*(n+1)/2; }int main(){ while(~sdd(n,k)){ ll ans=(ll)n*k; for(ll l=1,r;l<=n;l=r+1){ if(k/l) r=min(k/(k/l),(ll)n); els...2021-02-27 11:39:1526
0
-
原创 洛谷 P4281 [AHOI2008]紧急集合 / 聚会(树剖+lca)
如果有两个点,那么最短的位置一定是两点中的 lca,此时有三个点,我们观察 6 3 1 这组询问,如上图所示:最后的答案为 2,也就是 3 6 的 lca,不妨可以猜测,最后的位置一定是在某两点的 lca 处,所以枚举即可代码并没有采用倍增,而是采用树剖来处理 lcaconst int N=5e5+5; int n,m; int i,j,k; int a[N]; vector<int> G[N];int dep[N],fa...2021-02-27 10:10:1519
0
-
原创 洛谷 P1247 取火柴游戏(nim 游戏)
简单说一下 nim游戏 的博弈原理,先将 a[i] 转化成二进制数,那么题目变成了每一次可以取走任意 a[i] 的 任意个 1sum 是所有 a[i] 的异或值如果 sum=0,说明有偶数个 1,先手拿 x,后手也拿 x,先手必败如果 sum!=0,我们考虑去掉一堆,这 n-1 堆相互异或得到的结果 res,剩下的那一堆为 x,如果 x>res,那么我们考虑将拿掉 x-res,那么剩下的那一堆与其余的 n-1 堆形成异或为 0 的必败局面,可以证明一定存在 x 使得 sum!...2021-02-26 22:21:0125
0
-
原创 洛谷 P1704 寻找最优美做题曲线(二分)
首先要判断必刷题的 k 天是否能成立其次在剩下的天数中找到最长子序列,注意剩下的天数中可能会与必刷题的 k 天产生冲突,所以要有取舍,这里开了一个 vis 数组保存能够统计的天数最后在求最长上升子序列的问题中利用 nlogn 的方法解决const int N=5e5+5; int n,m; int i,j,k; int a[N]; int p[N]; bool vis[N]; int s[N],top=0;void ini...2021-02-22 23:11:4114
0
-
原创 洛谷 P1663 山(二分)
题目出得比较妙,我们可以思考枚举高度,但是如何判断,根据题目中给出的图,如果 + 的位置向下移动,那么最右边的直线和最左边的直线都无法看到,这就是题目的突破口在 check 函数中,对于高度 h,根据每条直线的斜率枚举 h 可以出现 x 轴上的范围,判断是否可行,灯光与直线平行时题目默认是可以的const int N=5e4+5; int n,m; int i,j,k; double x[N],y[N]; double a[N],b[N];...2021-02-22 22:11:1815
0
-
原创 洛谷 P3041 [USACO12JAN]Video Game G(AC自动机+DP)
题目不难想到要应用 DP,建好 AC自动机之后dp[i][j] 表示到第i 个字符标号为j 的节点时最大的连击数是多少dp 方程也不难想由于本人实力欠缺,dp 数组的初始化为什么要设为 -1 没想明白,先给自己挖个坑 QAQconst int N=300+5; int n,m; int i,j,k; char s[N]; int t[N][3],tot=0; int vis[N],f[N]; int dp[(int)1e3+5...2021-02-22 21:20:1213
0
-
原创 洛谷 P3796 【模板】AC自动机(加强版)
题目要求出现最多的模式串及次数,我们目前可以利用 AC 自动机找到一个东西,那就是模式串这样不就好解决了吗?利用一个数组存取每一个模式串的出现次数,最后在统计一边就可以了const int N=1e6+5; int n,m; int i,j,k; char s[N]; int f[N]; int t[N][26],tot=0; int vis[N]; char ch[155][75]; int ans[N];int ...2021-02-18 22:07:4917
0
-
原创 洛谷 P3808 【模板】AC自动机(简单版)
AC 自动机模板题不做详细解释,但是强调几个代码中需要注意到的地方AC 自动机第一步利用字典树将模式串放入树中 第二步利用 BFS 构建 fail 指针,构造 fail 指针时需要注意,构建节点 u(x代表节点 u 中的字母)的 fail 指针时,是在其父节点位置时构造的,当 x存在时,其 fail 指针指向其父节点 fail 指针中的 x节点;而当 x不存在时,只要将 u 指向其父节点 fail 指针中的 x节点,这样可以在后续查找当中从字典树的底部跳到树顶(不明白...2021-02-18 20:42:5615
0
-
原创 洛谷 P2375 [NOI2014] 动物园(KMP+DP)
const ll mod=1e9+7;const int N=1e6+5; int n,m,t; int i,j,k; char s[N]; int f[N]; int dp[N];void getfail(char *s){ f[0]=f[1]=0; dp[0]=0,dp[1]=1; for(int i=1;s[i];i++){ int j=f[i]; while(j &&...2021-02-07 22:38:0316
0
-
原创 洛谷 P3435 [POI2006]OKR-Periods of Words(KMP+记忆化搜索)
题意不是很明确,我来解释一下样例 的前缀分别有,其中 Q 的长度分别为题目清楚之后,当 QQ 的前缀为 a 的时候,a-Q (即后缀)必须与 Q 的某前缀相同,Q 近可能大,所以 a-Q 尽可能小for(int i=2;i<=n;i++){ res=f[i]; while(f[res]) res=f[res]; if(res) ans+=i-res;}其中 f[] 为 next[] ,但是这样会超时,所以利用记忆化搜索, res[i] 表示到 i...2021-02-06 16:32:2831
0
-
原创 洛谷 P5149 会议座位(树状数组+Trie)
题目是一道求逆序对的题目,但是我们先要将每一个名字转化为数字再进行计算求逆序对的个数用树状数组或归并即可题目有个坑点,名字包含大小写字母,所以字典树需要开大一点#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#define ss(a) scanf("%s",a)#define sd(a) scanf("...2021-02-04 23:32:1925
0
-
原创 洛谷 P2580 于是他错误的点名开始了(Trie)
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#define ss(a) scanf("%s",a)#define sd(a) scanf("%d",&a)#define pd(a) printf("%d\n",a)#define rush() int T;cin>>T;w...2021-02-04 22:45:5519
0
-
原创 洛谷 P4391 [BOI2009]Radio Transmission 无线传输(KMP)
假设字串长度为 x,字符串从 1 开始计数next[1]=next[2]=……next[x]=0 next[x+1]=1 next[x+n]=n 发现从 x+1 位置开始,next 数组逐渐递增 1所以答案为 n-next[n]const int N=1e6+5; int n,m; int i,j,k; char a[N]; int f[N];void getfail(char *s){ int len=strlen(s); ...2021-02-04 10:18:1129
0
-
原创 洛谷 AT1219 歴史の研究(回滚莫队)
按照莫队的思路,添加一个数很简单,只要判断是否需要更新答案即可;但是删除一个数就要重新找的最值,时间复杂度 O(n)可以按照值域分块来做,但是值域分块没有回滚速度快的说const int N=1e5+5; int n,m; int i,j,k; int a[N]; struct Query { int l,r; int id; void read(){ sdd(l,r); } }q[...2021-02-02 22:32:4228
0
-
原创 洛谷 P4114 Qtree1(边树剖)
const int N=1e5+5; int n,m; int i,j,k; int a[N]; struct Node { int l,r; int maxx; #define lson id<<1 #define rson id<<1|1 }t[N<<2]; struct Edge { int u,v,w; ...2021-02-02 09:39:1516
0
-
原创 洛谷 P5268 [SNOI2017]一个简单的询问(莫队+容斥)
题目要求两个区间之间的关系,一定要容斥来做的,但是在 [r1,l2] 之间添一段来容斥是远远不够的令原式容斥的目的是将乘法关系转化为加法关系,但是此时函数 F 还是有乘法关系先考虑简单的,当给定的 n 个数都相同假设都为 2 吧我们发现每个区间都是 [1,x] 也就是说,有一种类似前缀的感觉所以在这里不得不对莫队进行改变,对于区间 [L,R] ,莫队的移动指针初始时 l=0,r=0,开始先移动指针 l,当 l<L 时,将每一个元素 2 全部放入桶中,直...2021-02-01 16:46:2922
0
-
原创 洛谷 P4315 月下“毛景树”(边树剖)
题目不算难,但是代码量需要控制主要说一下线段树上的操作,因为有两个相关的区间操作标记,应该先覆盖后增加,因为覆盖操作会影响增加操作const int N=1e5+5; int n,m; int i,j,k; int a[N]; struct Node { int l,r; int maxx; int lazy,add; #define lson id<<1 ...2021-01-28 15:11:1419
0
-
原创 洛谷 P3963 [TJOI2013] 奖学金(贪心+思维)
题目保证 n 为奇数首先找中位数我们是一定要排序的,按照成绩排序,在区间 [n/2+1,c-n/2] 中枚举 i 作为中位数,找到当 i 作为中位数时,左边 k 个最小的奖学金,和右边 k 个最小的奖学金,判断是否满足条件,取中位数的最大值即可。找区间内的前 k 个最值,没错,主席树,但是需要注意的是,在建树时一定是奖学金作为权值,但是有可能多个人同时拥有相同数目的奖学金。这里并没有采用主席树,采用前缀和+优先队列对于 i 为中位数来说,预处理出 i 左边拥有 k 个奖学金的最...2021-01-27 14:48:1422
0
-
原创 洛谷 P1383 高级打字机(主席树)
题目描述得不够准确,撤销时,可以将之前的撤销操作同时撤销这样题目就要求我们保留之前的所有数据,我们利用主席树维护一段字符串,长度为 1e5,假设全部是添加字符设当前的根节点为 now撤销操作相当于将之前的 now-x 节点复制过来,作为 now+1 根节点添加操作在区间的末尾添加一个字符查询操作,由于s[i] 字符放在 i 位置,所以直接查询第 x 个位置的字符即可const int N=1e5+5; int n,m; int i,j,k; ...2021-01-27 10:40:2221
0
-
原创 洛谷 P3939 数颜色(主席树)
题目要用权值线段树来解决没有问题,但是权值线段树还要维护所出现的区间,采用主席树,每一种颜色建一棵树,记录其所在的位置,由于建树过程中需要动态开点,更新操作时不需要动态开点,所以要特判一下是否要开点const int N=3e5+5; int n,m; int i,j,k; int a[N]; struct Node { int l,r; int sum; #define lson id&l...2021-01-25 22:11:1934
0
-
原创 洛谷 P3567 [POI2014]KUR-Couriers(主席树)
由于主席树是一颗特殊的权值线段树,所以只需要判断当前节点权值所拥有的数量是否大于 (r-l+1) 即可const int N=5e5+5; int n,m; int i,j,k; int a[N]; struct Node { int l,r; int sum; }t[N*40]; int root[N],tot=0; //历史版本根节点标号,总节点个数 vector<int> v...2021-01-25 20:17:2922
0
-
原创 洛谷 P3919 【模板】可持久化线段树 1(可持久化数组)
const int N=1e6+5; int n,m; int i,j,k; int a[N]; struct Node { int l,r; int val; }t[N*40]; int root[N],tot=0; //历史版本根节点标号,总节点个数int build(int l,int r){ int p=++tot; if(l==r){ t[p].val=a[l]; retu...2021-01-24 23:23:2924
0
-
原创 洛谷 P4396 [AHOI2013]作业(莫队+值域分块)
抱歉,一开始读错题了由于最后统计 [a,b] 中有多少数出现过,以及位于 [a,b] 内的数值个数由于这两个是相关联的,所以不好一起统计,所以采用暴力的方法,但是暴力一定超时,所以在这里使用分块写分块的时候到底需要几个参数,首先对于非整块,vis[x] x出现的次数;对于整块 cnt[x] x出现的次数,tag[x] x 出现的种数const int N=1e5+5; int n,m; int i,j,k; int a[N]; struct Qu...2021-01-24 21:37:3019
0
-
原创 洛谷 P4137 Rmq Problem / mex(莫队+值域分块)
看到这个题目后,删除 O(1) 添加 O(n),做法就是遍历区间 [now,n] 但是最后一个点会T看到有人说值域分块可以过,虽然最后一个点过了,但是前面又过不了了,最后还是要开 O2void add(int pos) //暴力添加代码{ int x=a[pos]; if(!vis[x] && now==x){ for(int i=x+1;i<=n+1;i++){ if(!vis[i]){ now=i; b...2021-01-24 18:23:3927
0
-
原创 洛谷 P4113 [HEOI2012]采花(树状数组)
又是一道莫队的模板题看到熟悉的 2e6 的数据量,应该也知道莫队跑步过去了,题目好不容易猜出了结论,但是却置疑他的准确这个题目和HH的项链这个题比较像同样此题也要采用树状数组来优化对于一个区间内出现的相同的颜色,我们只计算倒数第二个所做的贡献,算法的准确性:对于一个区间 [b.......a......a...c...a...d..A...e..a...f] (应该是不分大小写的)其中只有 A 对于答案有贡献,对于询问 [b,e] 或者 [c,e] 答案都只有 A...2021-01-24 15:08:0117
0
-
原创 洛谷 P3730 曼哈顿交易(莫队+值域分块)
题目应该算是莫队里面比较难的(蒟蒻的我自我安慰)求区间第 k 小数不由得想到主席树,但这是类似于众数的形式,所以还是考虑莫队但是莫队之前做过一道求众数的大小的题目,是否可以向这方面靠拢,一定要有一个数组记录 x 出现的次数,记为 a 数组。再添加一个出现过 x 次的数有多少次的数组,记为数组 b。以上两个数组是最基本的,我们要求区间内第 k 小的出现次数,暴力的话就是顺序遍历 b 数组数到 k,但是时间复杂度为 但是如果我们用分块处理一下 a 数组,这样复杂度不就变成,总体还是...2021-01-23 10:14:0820
0
-
原创 洛谷 SP10707 COT2 - Count on a tree II(树上莫队)
树上莫队,首先要将树上的编号映射至线性,这里采用欧拉序就样例来说,所谓欧拉序就是 {1 3 7 7 5 5 66 3 4 8 8 4 2 2 1} 其实就是要求我们在 dfs 过程中,将 x 节点进栈的时间编号和出栈的时间编号全部记录下来我们将进栈编号记为 st[x] 出栈编号记为 ed[x],再对区间进行操作时,同样分为两种情况如果查询区间 [u,v] 在同一条链上,比如 [1,5] 那么就是 [ st[1],st[5] ] 区间,注意,只有节点 1, 3 ,5 如果查询区间...2021-01-22 17:58:2820
0
-
原创 洛谷 P3709 大爷的字符串题(莫队+贪心)
题目其实是和这道题目一样的https://www.luogu.com.cn/problem/P1997题目中有一句话很重要将这段区间搞完后最多还会剩下多少 rp,对于题目给出的规则我们可以理解为如果区间不为空,答案为 0 存在 a∈ S,如果 a>=x ,那么清空 S,插入 a 任意 a∈ S,如果 a<x,那么直接插入 a规则可以理解为构造任意个严格单调上升子序列,但是为了使最后的答案最大,我们要保持构造的子序列的数量尽可能少,举个例子:我们已经构造了如...2021-01-21 22:06:4719
0
-
原创 洛谷 P4116 Qtree3(树剖)
题目中默认根为 1,2021-01-21 20:15:0121
0
-
原创 洛谷 P4092 [HEOI2016/TJOI2016]树(树剖)
题目能够像过来还是挺简单的,但想不过来就……如何将标记操作与查询操作联系起来标记操作,一开始的时候所有节点都是 1,如果修改一个节点,那么将这个节点所代表的子树全部修改,完成 查询操作,从当前节点向根节点 1 查询不就好了吗,这样做好像不太对,如果所处的节点是左子树,那么可能查询到右子树上,但是如果我们单点查询的话,将标记下放至当前节点不就好了吗const int N=1e5+5; int n,m; int i,j,k; int a[N]; ...2021-01-21 09:32:5519
0
-
原创 洛谷 P3038 [USACO11DEC]Grass Planting G(边树剖)
题目描述Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional roads, such that there is exactly one path between any two pastures. Bessie, a cow who loves her grazing time, often complains about how there is no grass on t2021-01-19 20:46:1729
0
-
原创 洛谷 P3833 [SHOI2012]魔法树(树剖)
题目中只要注意平时在找重儿子的时候是以 s作为根节点 s>=1 所以在此根节点为 0,要求我们将所有的节点编号 +1const int N=1e5+5; int n,m; int i,j,k; int a[N]; vector<int> G[N]; struct Node { int l, r; ll lazy,sum; #define lson id<<1...2021-01-19 16:48:0026
0
-
原创 洛谷 P3384 【模板】轻重链剖分(树剖)
树剖模板题,有几个注意事项并没有默认根节点,所以在标重儿子以及标 dfs 序的时候应该注意两遍 dfs 的写法 统计以 x 为根的所有节点的情况,即求 [x,x+size[x]-1] 区间内的节点,size[x] 数组表示 x 节点所拥有的孩子的数量const int N=1e5+5; int n,m; int i,j,k; int a[N]; vector<int> G[N]; struct Node ...2021-01-19 16:21:4920
0
-
原创 洛谷 P3097 [USACO13DEC]Optimal Milking G(线段树+dp)
题目中的修改为基本操作,但是究竟要维护什么,值得我们去讨论其实很容易想到左端点到底要不要,如果左端点要是一种情况,左端点不要有是一种情况当选择左端点时,最优的时候是不是将奇数位置上的所有点都取,还是说中间要变,这便是我们熟悉的动态规划线段的每一个点都维护一个区间内部端点的选择情况 f[i][j] 当 i =0 时,表示左端点不取,j = 0 时,表示右端点不取这样在 push_up() 函数中应用动态规划即可const int N=4e4+5;#define int ...2021-01-19 10:08:3926
0
-
原创 洛谷 P3604 美好的每一天(莫队)
题目描述回归天空是一件庄重的事情,所以卓司决定让大家分批次进行,给每个人给了一个小写字母'a'->'z'作为编号一个区间的人如果满足他们的编号重排之后可以成为一个回文串,则他们可以一起回归天空,即这个区间可以回归天空由于卓司是一个喜欢妄想的人,他妄想了m个区间,每次他想知道每个区间中有多少个子区间可以回归天空因为世界末日要来了,所以卓司的信徒很多输入格式第一行两个数n,m之后一行一个长为n的字符串,代表每个人的编号之后m行每行两个数l,r代表每次卓司妄想的区间.2021-01-18 14:35:1019
0
-
原创 洛谷 P3072 [USACO13FEB]Perimeter S(dfs)
题目保证所有的草堆构成连通块,我们可以用 dfs 很简单的获得各个草堆的相对位置如上图所示,白色的方块为草堆的位置,那么他的外周长是绿色的方块个数,其中红色方块个数的贡献是二,也就是说绕着外周长的外面走一圈,看看当前方格挨着几个草堆,这样通过 dfs 就可以将问题解决了。遍历所有的绿色/红色方块一次且仅以此,搜索到白色那么 ans+1,此方块的任务结束const int N=2e5+5; int n,m; int i,j,k; //int a[N];...2021-01-17 16:41:0934
0