07 2016 档案
摘要:主席树。 主席树复习,这道题是主席树的经典入门了吧。。 无修改区间第k大。 #include #include #include using namespace std; const int maxn = 200000 + 10; const int maxm = 5000000 + 10; /* void build(int &x,int L,int R) { if(!x)...
阅读全文
摘要:kmp+矩阵乘法。 好久以前做过,但我今天居然死活看不懂以前的程序,再写一发。 用f[i][j]表示前i个准考证号匹配了前j个不吉利数字的方案数。 tmp[i][j]表示匹配了前i个不吉利数字以后,增加一个字符可以匹配前j个不吉利数字的方案数。 我们可以枚举(i+1)位的数字,并用kmp求得的next数组进行转移,就可以求出tmp数组。 很显然有(就是我完全不知道为什么。。) f[i]...
阅读全文
摘要:矩阵乘法。 关于点的无法表示刚才走过的路不能走,所以用把边拆成俩个来建图,自己不能和自己连。 然后再用俩点表示起点和终点。 快速幂求矩阵(t+1)次就可以了(t+1次是因为到达终点那条边就需要t次,然后新建了一个终点,就会多走一步)。
阅读全文
摘要:矩阵乘法。 邻接矩阵用矩阵乘法可以得到最后的方案数 食人鱼是周期性的移动可以用12个矩阵表示。12个矩阵乘在一起得到第13个矩阵。 然后k/12的部分用第13个矩阵快速幂转移,再乘下剩余的矩阵。 #include #include #include #define LL long long using namespace std; const int maxn = 50 + 10;...
阅读全文
摘要:树形dp。 这道题的划分方式和树链剖分类似,但是重路径能经过根节点,而且要求方案数,所以不能用树链剖分。 但是由这种关系可以知道答案很小为log n级别(翻看数据后,确认了答案最大为4。。但应该有能使答案更大的数据) 用f[i][j][0/1/2]分别表示,以i为子树的节点中,不便利值最大的点不便利值为j。 0代表i节点不在任何一条儿子构成的链中,1表示在一条和儿子构成的链中,2代表...
阅读全文
摘要:LCS+树状数组。 O(n^2)的朴素算法显然不可以。 但是根据朴素算法的递推式可知,只有a[i]==b[j]时,f才会更新。 而题目中相等的字符有且只有5个。 对于当前数,枚举它在另一个串的位置,更新答案。 重点是要发现更新的条件减少枚举次数。 #include #include #include using namespace std; const int maxn = 10...
阅读全文
摘要:循环 题解:http://trinklee.blog.163.com/blog/static/238158060201482371229105/ 刚开始把问题想的复杂了,想到了bzoj覆盖问题,但是俩者之间没有什么关系。那个是二分取得最大值。 本道题里,覆盖方式只可能出现题解里的6种。所以统计好前缀和就可以了。 各种变量要看清。 #include #include #include...
阅读全文
摘要:区间dp。 用f[l][r]表示从l到r最少需要染几次色。 状态转移方程: 1.f[l][r]=min(f[l][i],f[i+1][r]) (l #include #include using namespace std; const int maxn = 200 + 10; int n; int f[maxn][maxn]; char s[maxn]; int dp(int l,in...
阅读全文
摘要:主席树。 我分不清主席树和可持久化线段树。。 用主席树记录历史版本。 然后每个节点保存一个深度,代表以自己为根的树的深度。 合并时将深度小的树合进深度大的树。 3673也是一样的,不过那道题不强制在线。 #include #include #include using namespace std; const int maxn = 200000 + 10; const int m...
阅读全文
摘要:区间dp。 用f[l][r]表示区间[l,r]最短能缩到多短。 然后状态转移方程有俩种 1.不折叠 f[l][r]=f[l][i]+f[i+1][r]. (l= #include #include using namespace std; const int maxn = 200 + 10; char s[maxn]; int f[maxn][maxn]; int h(int i,i...
阅读全文
摘要:区间dp。 bool t代表区间内是否能含M。 如果不能含M的话有 res=min{f[l][i][0]+r-i}。(i>1][t]+1) (后半串用1个R替代)。 如果t=1时,除上面俩个还有res=min{f[l][i][1]+1+f[i+1][r][1]}。 状态和3种状态转移方程比较难想。很大程度是因为对区间dp不熟悉。 #include #include #include...
阅读全文
摘要:区间dp。 用f[l][r]代表从l合并到r的最小得分。 显然 r-l #include #include using namespace std; const int maxn = 100 + 10; const int inf = 0x3f3f3f3f; int n; int a[maxn],f[maxn][maxn]; int dp(int l,int r) { if(f[l...
阅读全文
摘要:主席树。 求a到b的路径可以看作a到根和b到根的路径的一部分。 对于每个节点,需要查询它到根路径各个数出现的次数。 如果对于每个节点都建一棵权值线段树,肯定会爆掉。 这时用主席树,该节点的权值线段树由父亲的权值线段树转移而来。 建树之前,要对整个数进行重标号,建树的时候才能保证父亲的树已经被建了。 #include #include #include using namespac...
阅读全文
摘要:权值线段树。 要求 L #include #include #define LL long long using namespace std; const LL inf = 10000000000ll; const int maxn = 100000 + 10; const int maxm = 8000000 + 10; struct segtree { LL l[maxm],r[...
阅读全文
摘要:dp。 首先这棵树是一个treap。 权值我们可以改成任意实数,所以权值只表示相互之间的大小关系,可以离散化。 树的中序遍历是肯定确定的。 用f[l][r][w]表示中序遍历为l到r,根的权值必须大于w的最小代价。 当a[x].ww时,还有f[l][r][w]=min(f[l][x-1][w]+f[x+1][r][w]+s[l][r]).不用修改了。 对于[1,n]来说,根的权值只存在...
阅读全文
摘要:数位dp。 数位dp一直掌握的不好。 用数位dp求出含若干个1的数的个数。 #include #include #include #define LL long long using namespace std; const LL maxn = 60; const LL mod = 10000007; LL C[maxn][maxn],a[maxn]; LL n,res,cnt; ...
阅读全文
摘要:半平面交。 半平面指的就是一条直线的左面(也不知道对不对) 半平面交就是指很多半平面的公共部分。 这道题的解一定在各条直线的半平面交中。 而且瞭望塔只可能在各个点或者半平面交折线的拐点处。 求出半平面交,枚举即可。 #include #include #include #include #define eps 1e-7 using namespace std; const int...
阅读全文
摘要:玄学,位运算。 首先1到n的路径可以看作一条简单路径和套很多环。由于异或的特性直接走和绕环一次再走是有区别的。 预处理出所有的环。 然后用一种类似于gauss消元的方式使每一位尽量为1(就是每个数都只有一位为1,剩下为0)。 然后和res异或就可以了。 #include #include #include #define LL long long using namespace ...
阅读全文
摘要:树形dp。 本来是想做一系列树分治的,结果这道题树形dp就可以了(膜popoqqq大神) f数组保存每个节点距离为0,1,2的点对数量。 不断统计就可以辣。 #include #include #include using namespace std; const int maxn = 20000 + 10; const int maxm = 40000 + 10; stru...
阅读全文
摘要:树分治。 网上有部分人的题解写的啥呀。。。 按重心进行分治。 首先O(n)算出以当前点为根depth(u)+depth(v) #include #include using namespace std; const int maxn = 10000 + 10; const int maxm = 20000 + 10; const int inf = 0x3f3f3f3f; int g[max...
阅读全文
摘要:2-SAT。 首先有平面图定理 m #include #include using namespace std; const int maxn = 10000 + 10; const int maxm = 3000000 + 10; int g[maxn],v[maxm],next[maxm],eid; int a[maxn],b[maxn],c[maxn],pos[maxn]; bool t...
阅读全文
摘要:2-SAT。 读入用了黄学长的快速读入,在此膜拜感谢。 把每对时间当作俩个点。如果有交叉代表相互矛盾。 然后tarjan缩点,这样就能得出当前的2-SAT问题是否有解。 如果有解,跑拓扑排序就能找出一个特定的解。 #include #include #include using namespace std; const int maxn = 5000 + 10; const int...
阅读全文
摘要:2-SAT。 tarjan缩点。强连通分量的点要选一起选。 #include #include #include using namespace std; const int maxn = 20000 + 10; const int maxm = 200000 + 10; int n,m; int a[maxn],b[maxn]; int g[maxn],v[maxm],next[ma...
阅读全文
摘要:2-SAT。 好像很复杂的样子所以还在慢慢摸索。。。 这道题只需要tarjan缩点就可以了,如果有一个材料的满式和汉式同时被选中,代表不可能实现。 #include #include #include using namespace std; const int maxn = 5000 + 10; int g[maxn],v[maxn],next[maxn],eid; int n,m,...
阅读全文
摘要:状压dp。 500分解质因数的话,除了最大的质因数只需要8个质数,用二进制x储存,最大的质因数用y来储存(若没有比那8个质数大的质因数就使y=1) 用f[i][j]表示第一个人方案为i,第二个人方案为j时的方案数。 递推时用p[0/1][i][j]表示第1/2个人选当前数,i和j分别为两人方案时的方案数。 有f[i][j]=(p[0][i][j]+p[1][i][j]-f[i][j])%m...
阅读全文
摘要:费用流加动态建点。 考虑加的点是倒数第几个做的菜,它对答案的共享就是i倍的时间。 和bzoj1070修车那道题一样。 #include #include #include using namespace std; const int maxk = 100 + 10; const int maxn = 10000 + 10; const int maxm = 2000000 + 10; ...
阅读全文
摘要:树形dp。 好坑的dp。不会。 f[i][j][k]表示第i件装备和它的基础装备一共花费j个金币且向上提供j个装备时能取得的最大的力量值。 #include #include #include using namespace std; const int maxn = 100 + 10; const int maxm = 2000 + 10; int g[maxn],v[maxm],n...
阅读全文
摘要:数论综合。费马小定理,lucas定理,中国剩余定理,exgcd,快速幂,乘法逆元。 首先要计算出n的每个约数,简单的sqrt(n)枚举即可。 然后计算C(i,m)(m个中挑i个的组合数,ps:因为网上正反俩种都有,所以标注一下。。) 设s=sum(C(i,m)) 题目要求g^(s)%mod, 由费马小定理得 g^(s)=g^(s%(mod-1))。所以这里需要特判一下g是否等于mod。 ...
阅读全文
摘要:斜率优化+树分治。 点分治:找出当前子树的重心,分治根到重心这一段,更新根到重心这一段的值,将剩下的点按能到达的高度从低到高排序,更新。分治其他子树。
阅读全文
摘要:LCT. 将边按a从小到大排序后不断往进加,出现环就把b最大的边去除掉。 lct中边也要单独建一个节点保存边权。 #include #include #include using namespace std; const int maxn = 200000 + 10; const int maxm = 800000 + 10; const int inf = 0x7f7f7f7f; ...
阅读全文
摘要:高精度+排列组合。 如果计算老师能挨在一起的情况 有 (n+2)! * A(n+3,m) 老师一定挨宰一起的情况 有 2*(n+1)!*A(n+2,m)。 相减就是答案。 #include #include #include using namespace std; const int maxn = 3000; const int mod = 10000; struct bigin...
阅读全文
摘要:卡特兰数。 这道题打下表可以看出前几项是卡特兰数(怎么想到打表和卡特兰数?我事先看了题解,为了确认一下。) 因为p不是质数,所以不能用乘法逆元。 我们可以把C(2*n,n)/(n+1)的每一项分解成一个质数,然后乘,这样就可以了。 #include #include #include #define LL long long using namespace std; const i...
阅读全文
摘要:容斥原理。 先求出所有只含6和8而且不是其他数的倍数的数。 然后进行容斥dfs,小心爆long long。 #include #include #include using namespace std; typedef long long LL; const int maxn = 30000 + 10; LL a,b,cnt,n; LL lucky[maxn]; bool fl...
阅读全文
摘要:bfs+最小树形图+kruskal算法。 最小树形图形象地来说就是有向图的最小生成树,这个不能拿kruskal算法或者是prim算法直接求,否则会错。 就是w[u][v]!=w[v][u]的情况。 而这道题用朱刘算法肯定是行不通的。 但是这道题的有向边并不是边的性质,而是点的高度决定的。这样我们就可以分层求最小生成树。 如果加进高度为h的点,只需用kruskal算法选最短的边就可以了,而...
阅读全文
摘要:矩阵。 一个图的邻接矩阵的m次幂相当于 长度恰好为m的路径数。这要求边权为1。 因为边权小于等于9,所以可以把一个点拆成9的点。 拆成的第(i+1)个点向第i个点连边。 如果存在边(u,v,w) 就由u点向v拆成的第w个点连边,这样表明w次以后就可以到达v点。 这个拆点很牛啊,不过第一眼连邻接矩阵都没看出来。。 #include #include #include using na...
阅读全文
摘要:dp. 用f[i][j]表示长度为i,开头数为[1,j]的第一位下降的序列个数。 f[i][j]=f[i][j-1]+f[i-1][i-j]。 f[i-1][i-j]可以表示长度为i-1,开头数为[1,j-1]的第一位上升的序列个数。(各位取反以后,俩者一一对应,所以值相同) 要使用滚动数组。 好像%2和&1性能上没差别。 #include #include #include u...
阅读全文
摘要:仙人掌。 仙人掌入门题。。不过入门都好难。。。 题解好复杂。。 总体来说,没有环的话,就是一棵树,很好求。 如果有环的话,就找出这个环,用一个单调队列用环上俩个点对更新答案。(如果不用单调队列就O(n^2)超时) #include #include #include using namespace std; const int maxn = 3000000 + 10; in...
阅读全文
摘要:线段树。 真还就是个线段树。。 除去操作1,2的话,线段树很容易就处理了,问题在于如何处理操作1和2。(这点没想到)。。 我们用一个delta维护操作1,如果没有旋转就+k,不然就-k。 每次读入i和j的时候用trans处理一下,就成功在O(1)的时间解决了操作1和2。 细节很重要。 #include #include #include using namespace std; ...
阅读全文
摘要:spfa+dp。 首先用一个类似spfa的过程求出a[s][t],聪聪在s,可可在t时,聪聪第一步怎么走。 然后dp求出f[s][t],表示聪聪在s,可可在t的期望步数。 #include #include #include using namespace std; const int maxn = 1000 + 10; const int maxm = 2000 + 10; int...
阅读全文
摘要:AC自动机. 统计每个字符串在自己和其他字符串中出现的次数。 ac自动机的概念,首先有个trie树保存了所有的字符串。 fail指针指向该字符串的后缀在整个trie树中可以做最长的前缀的位置。 每个字符串都可以由fail指针转移到是该字符串字串的位置。 所以很多统计就可以进行辣。 字符串的题好难。。 #include #include #include using namesp...
阅读全文

浙公网安备 33010602011771号