09 2017 档案
摘要:树形dp 就是求每个点到标记的点的最大距离 一个经典模型 有一个巧妙的方法,我们求出以这些关键点的直径,然后每个点到关键点的最大距离就是到直径两端的距离 #include<bits/stdc++.h> using namespace std; const int N = 100010; int n,
阅读全文
摘要:线段树+并查集 这道题跟codeforces #416 div2 E几乎一样 于是我又抄了一遍代码 我们建线段树,维护l->r区间这一块黑色白色连通块的数量,并且维护两端的并查集,每次合并区间就是把并查集合并,计算颜色的变化数量,并查集具体是维护一个fa数组,每次合并的时候把两端的并查集信息放到fa
阅读全文
摘要:贪心 想了一会觉得没什么很好的方法,看了题解 我们枚举每个二进制位,对于l,r如果这位相同就异或到答案里,否则停止,这里肯定是r比l大,也就是r这位是1而l是0,那么我们就让r这位选1,l选0,然后把l从这位-1直到0每位全部赋成1,这样就是答案 为什么是对的呢?考虑如果这位不同,那么之前的位全部都
阅读全文
摘要:数位DP 昨天的B题,excited 又学习了一下数位dp... 数位dp要考虑几个比较重要的东西:1.前导0,2.天际线,3.记忆化的条件,4.细节 经常数位dp会问我们l->r区间中满足某某条件的数的个数,这个条件很明显满足可减性,所以一般转化为1->r的数-1->l-1的数,采用记忆化搜索的方
阅读全文
摘要:最小流 我很清楚知道自己已经忘记最小流怎么写了 是一个最小流,每行向每列连容量为1的边,源和汇分别向行和列连下界为限制,上界正无穷的边,然后就是跑最小流了。 我们先跑一个可行流,那么我们得先改造这个图,引入超级源汇,如果一个点流出去的比流进来的多,那么连向超级汇,否则超级源连过来,跑一遍dinic,
阅读全文
摘要:fft+manacher fft都快忘了。。。 其实我们发现,这个问题是可以用fft做的,因为是回文子序列,所以我们直接自己和自己求卷积,然后扫描每个位置,注意是每个位置,因为包括奇数长度和偶数长度,f[i]为第i个位置上的对称字符的数量,那么一共就有(2^f[i])-1个回文子序列,因为是要不连续
阅读全文
摘要:manacher 先用manacher求出p数组,f[i]表示以i结尾最靠左的回文中心,那么每次用i-f[i-p[i]]更新答案就可以了,感觉十分巧妙...... #include<bits/stdc++.h> using namespace std; const int N = 200010; i
阅读全文
摘要:manacher+set 好像这种求回文串形态的都是用manacher,然后求出中心之间奇怪的关系 我们先跑出来manacher,由于只要偶数回文串,我们就只把#位置记录下来,重新保存,然后我们考虑什么情况下区间[x+1,y]*4可以更新答案,x是整个回文串的中心。那么很明显有x+f[x]/2>=y
阅读全文
摘要:dp 设dp[i][j]为当前到了第i个位置,一共出现了j个逆序对,然后考虑转移,因为前面只有i-1个数,所以这位只能产生[0,i-1]对逆序对,那么dp[i][j]=sigma(dp[i-1][k]),k∈[i-j+1,j]。 但是这样直接搞是O(n^3)的,那么我们用前缀和优化一下,就是O(n^
阅读全文
摘要:费用流+线段树 看见这个题我们马上就能想到费用流,设立源汇,分别向每个点连接容量为1费用为0的边,然后相邻的点之间连边,费用为点权,跑费用流就行了,但是很明显这样会超时,那么我们要优化一下,我们观察费用流的过程,发现对于点与点之间的边,每次取一段区间相当于把正向边改为反向边,费用变负,于是我们可以用
阅读全文
摘要:dp+spfa优化 最朴素的dp是dp[i][j]表示i->j的最短路,然后把所有pair(i,i)放到队列里跑spfa,但是这样被卡掉了,那么我们要优化一下 问题在于每次我们转移的时候要枚举i和j的邻居,这样会被两个连起来的菊花卡掉,那么我们希望一次只走一步,那么复杂度会大大降低,于是我们设一个状
阅读全文
摘要:树的直径+单调队列 这竟然和bzoj1999是一样的? 我们yy一下,发现这条路径肯定在树的直径上,然后就好办了,我们维护一个双指针,保证长度<=s,然后最大距离就是直径的两端到路径的两端的最大值,还有当前路径上挂着的链,这个我们dfs一下就行了,然后直径两端的最大值直接求就行了,链的最大值维护一个
阅读全文
摘要:裴蜀定理 有这样一个定理,ax+by能凑出最小的正整数=gcd(a,b),那么这里正好符合我们要求的东西,先开始我还想不明白6和4是怎么配出2的 然后我们就把每个数质因数分解,最多sqrt(n)个,放到一个map里统计次数,如果一个因子出现次数大于等于k就和他取max,最后就是答案 #include
阅读全文
摘要:线段树 额 计蒜客竟然把这个出成noip模拟题。。。 这个东西很像1018,只不过维护的东西不太一样 具体有这五种情况,合并请看代码,自己写了一个结果wa了,然后就copy了一下。。。 然后build的时候不用把叶子结点的值赋成inf,感觉奥妙重重 #include<bits/stdc++.h> u
阅读全文
摘要:线段树优化建图+费用流 朴素的做法是每个强盗直接对每个区间的每个点连边,然后跑最大权匹配,这样有5000*5000条边,肯定过不去,那么我们用线段树优化一下,因为线段树能把一个O(n)的区间划分为O(logn)段 然后就建一棵线段树,每个节点向两个儿子连(inf,0)的边,叶子结点连向sink,(1
阅读全文
摘要:期望dp n久以前做过,再做一遍 你只能决定决策,不能决定结果,这是这道题的关键,因为我们换了教室不一定成功,所以我们应该这样设dp状态,dp[i][j][k],第i天,换j次,换没换,转移: dp[i][j][0] = max(dp[i-1][j][0] + dis[c[i-1]][c[i]],
阅读全文
摘要:线性筛+莫比乌斯反演 盗波图 来自candy?大神 反演很重要的一条公式就是[gcd(i,j)==1]= 线性筛怎么推呢? 我们分4个步骤,1.先推出f[1],2.推出f[p],p是一个质数,3.由于线性筛筛的是积性函数,那么当gcd(i,p[j])==1的时候,f[i*p[j]]=f[i]*f[p
阅读全文
摘要:二分+树剖+差分 之前的做法naive,莫名其妙的wa,明明uoj95分 看到最小最大上二分,树上路径问题直接剖,然后问题就转化成了一个判定问题,每次二分出最长路径长度,问能不能达到。那么我们就把所有长度大于二分出的d的路径拉出来,求出他们公共路径的最大长度,看减去能不能满足。那么现在的问题就转化成
阅读全文
摘要:后缀数组+kmp+set 前两个条件很好搞,后缀数组求lcp然后看相邻两个后缀是不是分别属于不同的串,是的话所有lcp的max就是答案,但是现在有了第三个限制就很麻烦了。 我们先把第三个串在第一个串上跑kmp,把所有匹配位置的结束点放进set里,然后像之前一样查lcp,每次查的时候在set里查询当前
阅读全文
摘要:欧拉函数+逆元 并没有什么想法 gcd有一个性质,gcd(i,j)=gcd(i+j,j),这个性质有什么用呢?我们发现phi(m!)找出了在m!以内所有和m互质的数,但是我们没有找到在n!范围内的数,但是根据刚才的性质,gcd(i,j)=gcd(i+j,j),那么gcd(i,m!)=1,gcd(i+
阅读全文
摘要:树形dp %%%popoqqq 设dp[i][j]表示当前i个节点的树,深度小于等于j的树的个数 那么dp[i][j] = sigma(dp[k][j-1]*dp[n-k-1][j-1]) 比较好理解 然后记忆化搜索就行了 这个dp状态感觉挺巧妙的,以前没见过 #include<cstdio> #i
阅读全文
摘要:dp 看了挺长时间的,这篇写的很好:http://97littleleaf11.xyz/oi/bzoj-2660/ 我们先把n按照斐波那契数列贪心分解,然后发现可以把现在组合的斐波那契数分解成两个较小的,具体看博客,然后就是dp转移,上面的博客图画的很清楚了,转移就很方便 #include<cstd
阅读全文
摘要:费用流 比较裸的费用流,唯一的问题在于费用,由于费用是单调递增的,那么我们可以拆边,源点连向每个人source->i,f=ti-ti-1,c=w,这样就好了,因为费用递增,所以符合费用流的贪心思想,肯定先选小的费用,再走大的费用 #include<bits/stdc++.h> using names
阅读全文
摘要:容斥原理 计蒜客比赛day2t3的简化版 总数-异色三角形 对于每个点考虑,每个点红线数量为d[i],那么以这个点为顶点的异色三角形有d[i]*(n-1-d[i]),每条红线和蓝线成一个异色三角形,一共有n-1条线引出,然后再除以2,因为每个异色三角形会算两个顶点,也就是算两次。 #include<
阅读全文
摘要:区间dp 这道题就是把区间dp套了一件树的外衣,看见这种构造二叉搜索树的题,就可以用区间dp解决,如果优化的话似乎可以用决策单调性? dp[l][r]表示l->r这些节点构建一颗二叉搜索树的最小频率,那么我们用记忆化搜索转移,dp[l][r]=dp[l][i-1]+dp[i+1][r]+k*(sum
阅读全文
摘要:set+贪心 感觉当div2C挺好的... set维护前缀和%m,当前答案为sum[r]-sum[l-1],我们当然希望sum[l-1]是sum[r]的后继或者最小的数,所以求出来比较一下就行了 #include<bits/stdc++.h> using namespace std; int n;
阅读全文
摘要:C:这道题没做出来...写了个类似极角排序的东西被卡掉了...事实上暴力就行了,因为如果在二维平面内那么最多只能有4个点,因为每个象限只能有一个点,然后这里拓展一下就是最多只能有2*k个点,k是维数,所以大概枚举2*k=10就跳出循环了 #include<bits/stdc++.h> using n
阅读全文
摘要:A:枚举一下就行了...居然wa了一发,题目一定要看清 #include<bits/stdc++.h> using namespace std; int n; int main() { cin >> n; int mid = n / 2 - ((n & 1) == 0); for(int i = n
阅读全文
摘要:gcd 跟那道cf题是一个原理。。。 每一时刻我们最多有log个gcd,那么我们用map存储每种gcd最左端,每次和新的数gcd就更新新的gcd的最左端,然后更新答案 #include<bits/stdc++.h> using namespace std; typedef long long ll;
阅读全文
摘要:CRT+LUCAS+费马小定理+拓展欧拉定理 幂指数太大了怎么办?欧拉定理,n太大了怎么办?上lucas,模数太大了怎么办?上crt。然后就好了,唯一注意的是要用拓展欧拉定理,n%phi(p)+phi(p) #include<cstdio> #include<cstring> #include<cm
阅读全文
摘要:KMP 我似乎复杂度写的不对。。。 因为位置相同只算一次,后缀数组什么的都不管用了,我们就暴力kmp,但是我写的是暴力跳。。。竟然过了。。。我写bzoj3670才发现。。。 #include<cstdio> #include<cstring> #include<algorithm> using na
阅读全文
摘要:虚树+树形dp 虚树一类问题是指多次询问,每次询问的点数较少,如果我们每次都对整棵树进行遍历,那么自然是不行的,这时我们就构造出一棵虚树来降低复杂度 具体构建就是把一些无用的点缩起来。我们考虑对于一个点包括自己和这个点的子树,我们怎么构建虚树。 我们把所有点按dfs序排序,也就是模拟出dfs的过程,
阅读全文
摘要:二维线段树 听说二维线段树不能下传标记? 就是裸的二维线段树,由于每次高度只能增加,所以我们就可以标记永久化 每个线段树里有两个数组,mx和mark,每次修改路径上所有mx都要修改,mark是区间的精确覆盖修改 每次查询把路径上所有mark取max,然后和精确覆盖区间mx取max 为什么这样做呢?我
阅读全文
摘要:树上差分 感觉挺巧妙的。。。 每次更新就是在u,v上+1,x是lca(u,v),在x和fa[x]上-1,那么每个点的权值就是子树和,正确性yy一下就行了 不过树状数组的常数真是小,改成前缀和才快了200ms #include<bits/stdc++.h> using namespace std; c
阅读全文
摘要:A:略坑 枚举l-r,看是否能整除k且商的范围是不是在x,y里 #include<bits/stdc++.h> using namespace std; int l, r, x, y, k; int main() { cin >> l >> r >> x >> y >> k; for(int i =
阅读全文
摘要:线段树+离线 这种题既可以用莫队做也可以用线段树做,跟hh的项链差不多 首先我们处里出前缀mex,也就是1->i的mex值,再预处理出每个数下一次出现的位置,然后把每个前缀mex插入线段树,每个节点表示l==r表示1->l的mex,然后把询问按左端点排序,依次查询,修改每次把小于当前左端点的数的影响
阅读全文
摘要:差分约束系统 按题目建边就行了,大于等于号是最长路,小于等于号是最短路,边由减号后面连向减号前面,边权是不等号后面的常数项 这里跑最长路,用dfs版spfa跑 #include<bits/stdc++.h> using namespace std; const int N = 10010; stru
阅读全文
摘要:差分约束系统 我们把前缀和看成一个点,每个点之间的关系就是sum[i]-sum[j-1]=?,然后我们拆成sum[i]-sum[j-1]>=?和sum[j-1]-sum[i]>=-?,大于等于号是跑最长路,边从b连向a,边权是符号后面的常数项,然后跑最长路就行了,我们可以用dfs版spfa跑 #in
阅读全文
摘要:二分+贪心+动态规划 第一问就是二分+贪心,和跳石头挺像的 第二问是dp,dp[i][j]表示第i次切割切到了第j段木棍,转移就是dp[i][j] = sigma(dp[i-1][k]), sum[j]-sum[k]<=ans,ans是最大长度,这里第j段木棍表示现在正在分割1-j这些木棍。很明显这
阅读全文
摘要:计算几何 我们先把所有的线段求出来,我们发现只有两个线段等长且中点重合时才能构成矩形,那么线段有n*n条,我们按中点,长度排序,然后对于一条线段扫描所有符合条件的线段计算答案,这样看起来是O(n^3)次的,实际上远远到不了 但是1336和1765两道题空间较小,不能乱开空间 #include<bit
阅读全文
摘要:二分图匹配/并查集 其实我们发现,这里的方案就是希望从一开始一直能够被匹配上,那么我们就设立1-10000个点,一个装备向对应的属性连边,那么我们从1开始跑匹配,直到不能匹配结束。 但是这样很明显不是正解,我们把每个装备的两个属性之间连边,把小的属性连向大的属性,如果这两个属性已经相连,那么我们把大
阅读全文
摘要:卡特兰数 组合数优化 毫无头绪。。。 其实我们发现,我们可以把字符串的选择转换一下,我们建立坐标系,起初我们在原点(0,0),每次可以走(1,1)或(1,-1),希望最终到达(n+m,n-m),并且不经过y=-1 那么我们就可以用类似卡特兰数的方法解决这个问题,先算出随便走的方案数,我们一共要走n+
阅读全文