摘要: 首先将问题转化为2x^x=3x,那么相当于让x右移一位和原数的1不相交,即不含有相邻的1,第一个问题可以直接数位dp,第二个问题可以类似dp+矩乘优化即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 阅读全文
posted @ 2019-08-08 21:28 PYWBKTDA 阅读(145) 评论(0) 推荐(0) 编辑
摘要: 首先有暴力dp,令f[i][j][k]表示A中前i个与B中前j个分成k段的方案数,有$f[i][j][k]=\sum_{l=1}^{i}f[i-1][j-l][k-1](A[i-l+1,i]=B[j-l+1,j])$,显然这样时空复杂度都无法承受。进而考虑优化:l的取值一定是0<l<t,那么只要用前 阅读全文
posted @ 2019-08-07 19:58 PYWBKTDA 阅读(168) 评论(0) 推荐(0) 编辑
摘要: 首先二分枚举答案t,考虑删去的边应满足的条件——所有大于t的链全部经过且长度不小于最长链-t,第二个条件很好判断,考虑第一个条件。 先考虑有祖先-后代关系的链,用如果把这条链到1看成一个序列,那么差分一下再dfs一遍就可以对这条链上每一个点打上标记。 然后没有祖先-后代关系的链,同样可以分解成两条链 阅读全文
posted @ 2019-08-07 19:58 PYWBKTDA 阅读(211) 评论(0) 推荐(0) 编辑
摘要: 首先,我们肯定要用到二分答案。 这道题目就是统计第k个μ不是0的数,线性筛显然会炸飞的,但当二分出一个数而统计有多少个小于等于他的合法数时,就可以容斥一下,即:1^2的倍数都不合法,2^2的倍数都不合法……4^2的倍数已经通过2^2统计过且没有重复……6^2的倍数被3^2的倍数和2^2的倍数重复统计 阅读全文
posted @ 2019-08-07 19:58 PYWBKTDA 阅读(140) 评论(0) 推荐(0) 编辑
摘要: 定义dp[i]表示当前连通块状态为i的方案数(状态记录该状态每一个连通块的大小),那么从小到大枚举每条边,考虑这条边在不在最小生成树上: 1. 如果不在最小生成树上,那么这条边有$\sum_{i=1}^{scc}\sum_{j=i+1}^{scc}Si\cdot Sj$(Si表示第i个连通块的点数) 阅读全文
posted @ 2019-08-07 19:58 PYWBKTDA 阅读(140) 评论(0) 推荐(0) 编辑
摘要: 先解释一下checker.cpp,它的判定标准是2e7,即答案超过2e7就认为代价过大了。 首先,很容易想到的办法是直接对其快排,从外到内交换区间即可,然而这样会被邪恶的出题人给卡掉(当然其实随便一组大数据都能卡)。 由于一次操作可以翻转而不仅仅是交换,所以要将一个区间分成两块仅仅需要经左右两个区间 阅读全文
posted @ 2019-08-07 19:58 PYWBKTDA 阅读(158) 评论(0) 推荐(0) 编辑
摘要: 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 2000005 4 long long n,ans,f[N],vis[N],p[N]; 5 void mobies(int n){ 6 f[1]=1; 7 for(int i=2 阅读全文
posted @ 2019-08-07 19:57 PYWBKTDA 阅读(81) 评论(0) 推荐(0) 编辑
摘要: 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 ll n,ans; 5 ll phi(ll n){ 6 ll ans=n; 7 for(ll i=2;i*i<=n;i++){ 8 if (n%i==0 阅读全文
posted @ 2019-08-07 19:57 PYWBKTDA 阅读(94) 评论(0) 推荐(0) 编辑
摘要: 建立线段树,维护区间左端点选/不选,右端点选/不选且不含有相邻两个同时选的最大值,合并时注意细节即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mid (l+r>>1) 4 #define L (k<<1) 5 #defin 阅读全文
posted @ 2019-08-07 19:57 PYWBKTDA 阅读(133) 评论(0) 推荐(0) 编辑
摘要: 结论:最短路径一定是单独的一条边且在最小生成树上,可以用反证法证明。那么求出最小生成树,对于每一个点建立一棵权值线段树,再对每一个权值线段树上的叶子节点开一个multiset,维护所有儿子中该种颜色的权值(普通节点仍维护区间最小值),答案也需要用multiset维护。 1 #include<bits 阅读全文
posted @ 2019-08-07 19:57 PYWBKTDA 阅读(187) 评论(0) 推荐(0) 编辑
摘要: 题目要求其实相当于要让大于和小于m的数的个数都不超过n/2,因此当要对一个数处理时,要么把它改成m,要么不作修改,根据这个贪心就可以完成了。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 ll n, 阅读全文
posted @ 2019-08-07 19:57 PYWBKTDA 阅读(95) 评论(0) 推荐(0) 编辑
摘要: 分割实际上就是不断地从两端取出一样的一段,并对剩下的串进行分割。下面我们来证明一下每一次贪心取出最短一段的正确性: 考虑两种分割方式,分别表示成S=A+B+A和S=C+D+C,其中A就是最短的一段,那么当2|A|<|C|,显然就有C=A+E+A,那么就可以用三次划分来完成C,而当|A|<|C|<2| 阅读全文
posted @ 2019-08-07 19:57 PYWBKTDA 阅读(119) 评论(0) 推荐(0) 编辑
摘要: 记第i个位置有三个属性:1.ai表示原来的值;2.bi表示变成最大的值;3.ci表示变成最小的值。那么对于如果i在j的前面,那么必然有:$ai\le cj$且$bi\le aj$,那么令f[i]表示以i为结尾的最长上升子序列,即对求max(f[j])满足j能在i的前面,用树套树维护即可 1 #inc 阅读全文
posted @ 2019-08-07 19:56 PYWBKTDA 阅读(161) 评论(0) 推荐(0) 编辑
摘要: 用线段数维护一段区间内的两个信息:1.需要多少经验就可以让有一个人升级,2.等级和。单点修改直接暴力做就可以,区间修改考虑如果这个区间不会产生升级就不递归下去而是打上懒标记。 考虑这个算法的时间复杂度:单点修改的时间复杂度为$o(log_{2}n)$,而区间修改由于每一个点最多升级n+q次,总时间复 阅读全文
posted @ 2019-08-07 19:56 PYWBKTDA 阅读(74) 评论(0) 推荐(0) 编辑
摘要: 直接统计答案,令dp[i][j]表示前i个数最长的颜色各不相同后缀长度为j的方案数,如果一直令j<m,那么就相当于统计了方案数。 如何推出dp[i][j]呢?考虑i-1的最长前缀是多少:当小于j-1或等于j时,显然无法拼接成j;当等于j-1时,第i个位置就有m-j+1种方案;当大于j时,第i个位置对 阅读全文
posted @ 2019-08-07 19:56 PYWBKTDA 阅读(84) 评论(0) 推荐(0) 编辑
摘要: 发现加边操作不好处理,因此考虑先加完所有边后删边。 删去一对边x到y,如果两者中有一个不翘课显然没有意义,那么如果都翘课了那么就对他们进行判断,如果无法翘课就继续搜下去。 这样的时间复杂度看上去似乎是o(nm)的,但注意到每一个点最多由翘课变为不翘课一次,因此是o(n+m)的。 1 #include 阅读全文
posted @ 2019-08-07 19:56 PYWBKTDA 阅读(161) 评论(0) 推荐(0) 编辑
摘要: 小w喜欢的图可以发现就是一棵森林(是不是很神奇,其实易证:如果有环那么环本身就不合法,如果没有环那么显然合法)。继续研究发现删边最小<=>选边最大<=>最大生成森林,kruskal跑一下即可。 1 #include<bits/stdc++.h> 2 using namespace std; 3 st 阅读全文
posted @ 2019-08-07 19:56 PYWBKTDA 阅读(156) 评论(0) 推荐(0) 编辑
摘要: 定义f[i][j]表示从(i,j)走到最后一行的期望,不断从下往上dp那么对于每一行都可以得到m个方程。 但由于这m个方程不是DAG,因此考虑用高斯消元,但时间复杂度不对。 观察方程可以发现如果不断将f[i][j]表示出f[i][j+1]并代入那么就可以计算出f[n][m],再不断反代出来即可。 1 阅读全文
posted @ 2019-08-07 19:56 PYWBKTDA 阅读(135) 评论(0) 推荐(0) 编辑
摘要: 考虑令$b_{i}=a_{i+1}-a_{i}$,那么1操作相当于对L加上K,对(L,R]区间加上D,对R+1减去K+(R-L)*D,然后询问区间和即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define L (k<<1) 4 #de 阅读全文
posted @ 2019-08-07 19:55 PYWBKTDA 阅读(105) 评论(0) 推荐(0) 编辑
摘要: 考虑可持久化权值线段树,维护区间和那么发现满足条件的最多只有一个点,因此从若左区间有超过k个走左区间,右区间有走右区间,都没有就没答案 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 500005 4 #define mid 阅读全文
posted @ 2019-08-07 19:55 PYWBKTDA 阅读(84) 评论(0) 推荐(0) 编辑
摘要: 考虑A中第i次出现的j字符,最终位置一定是在B中第i次出现的j字符的位置,然后即求逆序对数量,cdq/线段树即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000005 4 #define L (k<<1) 5 #de 阅读全文
posted @ 2019-08-07 19:55 PYWBKTDA 阅读(94) 评论(0) 推荐(0) 编辑
摘要: 莫队,再用树状数组/线段树维护一下逆序对数即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 50005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 阅读全文
posted @ 2019-08-07 19:55 PYWBKTDA 阅读(125) 评论(0) 推荐(0) 编辑
摘要: 令ai=Hi/i,那么即求有多少ai满足对于任意0<j<i,都有aj<ai,可以理解为强制选择的LIS,以下简称LIS2。考虑分块,块内维护最大ai和块内的LIS2(具体的),然后不断枚举块并二分找到该块的LIS2中第一个大于曾经的max的值,并修改答案和max即可。还有一种线段树的做法,即维护区间 阅读全文
posted @ 2019-08-07 19:55 PYWBKTDA 阅读(111) 评论(0) 推荐(0) 编辑
摘要: 对Y分块,对于Y<K,每一次1操作暴力修改这个Y的最大值,时间复杂度o(K);对于Y>K,维护一颗权值线段树并查询大于iK且离iK最近的数,时间复杂度o(6000000/K)(还有一个log),大约取K=2000左右(可以不用权值线段树而用并查集维护,复杂度较低) 1 #include<bits/s 阅读全文
posted @ 2019-08-07 19:55 PYWBKTDA 阅读(93) 评论(0) 推荐(0) 编辑
摘要: 根据魔法值从大到小插入到线性基中,然后即输出线性基中的所有数之和 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 struct ji{ 5 ll id; 6 int k; 7 bool operato 阅读全文
posted @ 2019-08-07 19:54 PYWBKTDA 阅读(86) 评论(0) 推荐(0) 编辑