07 2019 档案

摘要:1.直接令x=0,为了判断这一信息,对于所有含有多个1的yi,必然是无用的,答案至少为n且不能含有多位1的y2.令yi=2^(i-1),由此发现一定可以得到x每一位的答案,即答案最多为n。因此,发现方案数即n!,当$n\ge p$时答案一定为0,时间复杂度为o(p) 1 #include<bits/ 阅读全文
posted @ 2019-07-28 19:58 PYWBKTDA 阅读(315) 评论(0) 推荐(0) 编辑
摘要:网络流建图,首先将所有价值加起来,用最小割考虑要删掉多少个价值:源点向每一个士兵连流量为x的边,士兵向汇点连流量为y的边,每一对关系间连流量为z的边,考虑有方程x1+y2+z=x2+y1+z=a+c,x1+x2=b+c,y1+y2=a+b,由于对称性(其实也不一定要对称),解得x1=x2=(b+c) 阅读全文
posted @ 2019-07-28 19:29 PYWBKTDA 阅读(253) 评论(0) 推荐(0) 编辑
摘要:有两个结论:1.排序后,答案一定是连续的三个数;2.当序列长度超过44一定有三个相同的数(因为即使该序列是斐波那契数列,此时也超过了1e9),然后用主席树等数据结构(略卡常,建议主席树)来维护前45大即可 1 #include<bits/stdc++.h> 2 using namespace std 阅读全文
posted @ 2019-07-28 19:18 PYWBKTDA 阅读(133) 评论(0) 推荐(0) 编辑
摘要:计算一对逆序对的贡献,即在n个数期望要删多少步才能删掉其中的两个数,设f(n)表示此时的期望,则有方程$f[n]=3/4+(\sum_{i=2}^{n}f[i]\cdot c(n-2,i-2))/2^n$,手算(打表)得到f[i]=4/3(代入成立),因此$ans=\sum_{i=1}^{n}(i- 阅读全文
posted @ 2019-07-28 19:03 PYWBKTDA 阅读(211) 评论(0) 推荐(0) 编辑
摘要:首先发现,最终第0辆车一定被堵在某一辆车前,那么等价于它的初始位置就在(那辆车的位置+中间车的车长)/那辆车的速度,其中最大的那个就是答案因此得出结论:$ans=max((\sum_{j=1}^{i}l[j]+s[i])/v[i])$,其中$i\in [0,n]$ 1 #include<bits/s 阅读全文
posted @ 2019-07-28 18:46 PYWBKTDA 阅读(154) 评论(0) 推荐(0) 编辑
摘要:令$m=\lfloor \sqrt[3]{n} \rfloor-1$ $\sum_{i=1}^{n}gcd(floor(\sqrt[3]{i}),i)$=$\sum_{i=1}^{m}\sum\limits_{j=i^{3}}^{(i+1)^{3}-1}gcd(i,j)+\sum\limits_{i 阅读全文
posted @ 2019-07-28 17:56 PYWBKTDA 阅读(253) 评论(0) 推荐(0) 编辑
摘要:$\sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j)\\$ $=\sum_{d=1}^{n}d\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\varepsilon(gcd(i,j))$ $=\sum_{d=1}^{n}d\sum_{g=1}^{n/d}\mu( 阅读全文
posted @ 2019-07-28 10:52 PYWBKTDA 阅读(241) 评论(0) 推荐(0) 编辑
摘要:直接令2i-1和2i的位置不相同,相当于有2n条边,对其进行二分图染色即可(这张图一定不存在奇环)。 假设给出的n条关系是A类边,2i-1和2i的边是B类边,可以发现一条路径一定是AB交替(因为A/B的终点一定不可能是A/B的起点),那么环就一定是有等量的A边和B边,即偶环。 1 #include< 阅读全文
posted @ 2019-07-28 10:52 PYWBKTDA 阅读(165) 评论(0) 推荐(0) 编辑
摘要:首先,从1和n跑一次dij,判断每一条边能否出现在最短路上,不能出现就删掉,然后将所有边建在图上,流量为边权,跑最小割即可。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 10005 4 #define ll long lo 阅读全文
posted @ 2019-07-28 10:51 PYWBKTDA 阅读(203) 评论(0) 推荐(0) 编辑
摘要:定义g[i][j]表示i个盘子在j柱上最终会移到哪个柱子上,f[i][j]表示相对应的所需步数。考虑转移,令k=g[i-1][j],第k根柱子最上面一个盘子在上一局已经移动6-j-k,因此这一步一定是将最大的盘子移到,总共移动f[i-1][j]+1步。再移动f[i-1][k]步,如果g[i-1][j 阅读全文
posted @ 2019-07-28 10:46 PYWBKTDA 阅读(124) 评论(0) 推荐(0) 编辑
摘要:由于最终的染色只与ci为几的个数有关,因此定义状态f[a][b][c][d][e][p]表示有a个ci=1,b个ci=2,……,有e个ci=5,上一次选择了ci=p的。状态的转移:发现p会让p-1少选一次,因此可以写出方程(详见代码),可以用记忆化搜索来写。 1 #include<bits/stdc 阅读全文
posted @ 2019-07-28 10:46 PYWBKTDA 阅读(205) 评论(0) 推荐(0) 编辑
摘要:二分答案+判定,对于一个答案,源点向每一个点连一条流量为1的边,每一扇门向汇点连一条流量为时间的边,每一个人向每一个在答案时间内能走到的门连一条流量为1的边,跑最大流并判断流量是否等于人数。 然而自从bzoj新增数据后就跑不过了,原因是不能保证有一组最优撤离方案使得在最后一个时刻以前(最后一个时刻可 阅读全文
posted @ 2019-07-28 10:45 PYWBKTDA 阅读(178) 评论(0) 推荐(0) 编辑
摘要:求最长反链(链上任意两个点不连通),可以发现,最长反链=最小链覆盖(因为每一条链都最多只有一个点入选),而DAG的最小链覆盖也就是最小路径覆盖(可相交)。然后floyd传递闭包,将任意两个连通的点都连一条边,这样就变成不可相交的最小路径覆盖(可以绕过去)。 不可相交的最小路径覆盖:将每一个点裂成两个 阅读全文
posted @ 2019-07-28 10:45 PYWBKTDA 阅读(96) 评论(0) 推荐(0) 编辑
摘要:1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 50001 4 int t,n,m,k,ans,mu[N],vis[N],p[N]; 5 void mobius(){ 6 mu[1]=1; 7 for(int i=2;i<N; 阅读全文
posted @ 2019-07-28 10:45 PYWBKTDA 阅读(79) 评论(0) 推荐(0) 编辑
摘要:有这样一个贪心的思路:当某一个点搜完某个儿子后,发现当前子树中没有被选入其他省的点数超过了B,就将其当做一个省,并把这个点作为省会(注意:这个点并没有进入这个省),显然可以发现此时每一个省的点数都小于2B。另外,当搜完后发现还有小于B的点,那么就将这些点都归入最后一个省,省的点数仍然小于3B。 1 阅读全文
posted @ 2019-07-28 10:45 PYWBKTDA 阅读(127) 评论(0) 推荐(0) 编辑
摘要:首先在所有点上放上士兵,如果初始不合法直接输出,否则考虑删除士兵。 对于每一个士兵,向所在行和所在列连边,每一行/列向汇点流最多能删掉多少个士兵,源点向每一个士兵流1的边,最后最大流即删掉的士兵。 1 #include<bits/stdc++.h> 2 using namespace std; 3 阅读全文
posted @ 2019-07-28 10:44 PYWBKTDA 阅读(107) 评论(0) 推荐(0) 编辑
摘要:首先考虑猪无法流动,那么源点向每一个猪圈连猪圈中猪个数的边,每一个顾客向汇点连所需猪的边,每一个猪圈向能打开它的顾客连inf的边,跑最大流即可。 但考虑猪要流动,有一个十分巧妙地做法,将每一个顾客所有有公共猪圈的顾客连inf的边,同时每一个猪圈只连向第一次打开它的顾客(也可以流向所有顾客,不过没必要 阅读全文
posted @ 2019-07-28 10:44 PYWBKTDA 阅读(103) 评论(0) 推荐(0) 编辑
摘要:题意是需要在某些相邻的节点中建立栅栏使得这两个点不能直接走到,使得所有狼的领地和羊的领地两两不能(间接)走到最少需要多少栅栏。 很显然,将S向所有羊连边,狼向T连边(流量为inf),然后任意相邻两个点连边(羊/狼之间可以不连),求最小割即可。 1 #include<bits/stdc++.h> 2 阅读全文
posted @ 2019-07-28 10:44 PYWBKTDA 阅读(181) 评论(0) 推荐(0) 编辑
摘要:将原图黑白染色,然后白点放左边,黑点放右边,原点向白点连点权的边,汇点向黑点连点权的边,白点向相邻黑点流inf的边,求最小割,用总权值减掉最小割即可。这样每相邻两个点一定有一个点的边被割掉,最小割就是最小的去掉的点,剩下的就是最大值了。 1 #include<bits/stdc++.h> 2 usi 阅读全文
posted @ 2019-07-28 10:44 PYWBKTDA 阅读(149) 评论(0) 推荐(0) 编辑
摘要:由于无法直接将果汁和饮料连边,所以将人放在中间,果汁和饮料放在两侧,然后分别向对应的人连边。同时,为了保证每一个人只被算一次,对每一个人裂点,两个点中间连一条流量为1的边。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 50 阅读全文
posted @ 2019-07-28 10:43 PYWBKTDA 阅读(104) 评论(0) 推荐(0) 编辑
摘要:对于每一个颜色用一个链表存储,并记录下:1.当前某种颜色的真实颜色;2.这种颜色的数量(用于启发式合并的判断);3.当前答案(即有几段),然后对于每一个操作简单处理一下就行了。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 阅读全文
posted @ 2019-07-28 10:43 PYWBKTDA 阅读(103) 评论(0) 推荐(0) 编辑
摘要:先建立最短路径树(即跑dij每一个点向更新他的点连边),考虑一个点的答案路径一定要走过且仅走过一条非树边,枚举非树边(x,y),对于一个点k,如果它在x~lca上(y~lca的路径上同理),那么答案可以更改为s[y]+len(x,y)+s[x]-s[k],前三个不受k的影响,因此越小越好,即将每一条 阅读全文
posted @ 2019-07-28 10:43 PYWBKTDA 阅读(194) 评论(0) 推荐(0) 编辑
摘要:考虑木板一定都尽量长,对于每一个污泥,最多只有两种木板会覆盖它(横着和竖的),将这两块木板连边,意味着每一条边两端端点中一定有一个点要被选,即最小点覆盖=最大匹配数。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 105 4 阅读全文
posted @ 2019-07-28 10:42 PYWBKTDA 阅读(164) 评论(0) 推荐(0) 编辑
摘要:将每一行/每一列作为一个点,对于一个障碍(x,y),要么第x行和第y列的状态(是否攻击)只需要有一个就可以了,将第x行和第y列连边,就是二分图的最小点覆盖=最大匹配数。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1005 阅读全文
posted @ 2019-07-28 10:42 PYWBKTDA 阅读(231) 评论(0) 推荐(0) 编辑
摘要:二分答案,每一头牛向所有在规定时间内能走到的牛棚连inf的边,每一个源点向牛连牛数量的边,每一个牛棚向汇点连牛棚容量的边,能满流则意味着这个答案可行,否则不可行。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 505 4 # 阅读全文
posted @ 2019-07-28 10:42 PYWBKTDA 阅读(116) 评论(0) 推荐(0) 编辑
摘要:同poj1741一样,只是将统计每一个点的深度改为深度除以3余数为0、1和2的点数量,注意(1,2)和(2,1)算两种。 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #de 阅读全文
posted @ 2019-07-28 10:41 PYWBKTDA 阅读(120) 评论(0) 推荐(0) 编辑
摘要:同[bzoj3894]文理分科,只是将五个点一组改为2个点一组(另外还可以通过解方程优化建边,但这里不需要)。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 60005 4 #define id (i-1)*m+j 5 #d 阅读全文
posted @ 2019-07-28 10:41 PYWBKTDA 阅读(92) 评论(0) 推荐(0) 编辑
摘要:由于k较小,因此考虑不断选取最大值,但同时还要删掉最大值。记f(k,l,r)表示以k为右端点时左端点在l~r之间的最大值,这个可以用线段树快速求出。当发现最大值是f(k,l,r)时,假设在位置t取到,则删除f(k,l,r)并加入f(k,l,t-1)和f(k,t+1,r),这个可以用堆来维护。初始时加 阅读全文
posted @ 2019-07-28 10:41 PYWBKTDA 阅读(96) 评论(0) 推荐(0) 编辑
摘要:对于三个点x、y和z,设a=lca(x,y),b=lca(x,z),不妨假设a的深度比b大,则b是a的祖先(因为a是x的祖先,b也是x的祖先)。 首先将集合点定在a,考虑a向每一个方向调整,a向父亲调整会让x和y答案加一,a向靠近x(y同理)的儿子调整,会让y和z答案加一,向其他儿子调整,会让三者答 阅读全文
posted @ 2019-07-28 10:41 PYWBKTDA 阅读(176) 评论(0) 推荐(0) 编辑
摘要:初始对于每一个叶子节点建一棵权值线段树,然后再线段树合并时计算一下两者分别在前面和后面的代价,$ans+=min(\sum sz[rz[x]]\cdot sz[ls[y]],\sum sz[ls[x]]\cdot sz[rs[y]])$ 1 #include<bits/stdc++.h> 2 usi 阅读全文
posted @ 2019-07-28 10:40 PYWBKTDA 阅读(136) 评论(0) 推荐(0) 编辑
摘要:同[bzoj1101]Zap,容斥即可。 1 #include<bits/stdc++.h> 2 using namespace std; 3 int t,a,b,c,d,k,f[50005],vis[100005],p[50005]; 4 void mobies(int n){ 5 memset( 阅读全文
posted @ 2019-07-28 10:40 PYWBKTDA 阅读(101) 评论(0) 推荐(0) 编辑
摘要:1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define mod 100000009 5 #define N 10000005 6 ll t,n,m,ans,c[N],f[N],vis[N],p 阅读全文
posted @ 2019-07-28 10:39 PYWBKTDA 阅读(116) 评论(0) 推荐(0) 编辑
摘要:根据每一个点到根的每一个点的权值建立n颗权值线段树(也就是一颗可持久化线段树/主席树),然后查询操作相当于对F[x]+F[y]-F[lca(x,y)]-F[fa[lca(x,y)]]这颗线段树作查询。 1 #include<bits/stdc++.h> 2 using namespace std; 阅读全文
posted @ 2019-07-28 10:39 PYWBKTDA 阅读(97) 评论(0) 推荐(0) 编辑
摘要:考虑一条边被选入最小生成树的条件,即所有比他小的边不能让这条边所连接的两个点连通,那么将所有边建成两条有向边并跑这两个点的最小割即可(最大生成树同理,但不可以一起做)。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 2000 阅读全文
posted @ 2019-07-28 10:39 PYWBKTDA 阅读(92) 评论(0) 推荐(0) 编辑
摘要:首先肯定每一位单独考虑,对于每一位,源点连向该位点权为0的节点inf的边,点权为1的节点连向汇点inf的边,每一条无向边拆成两条流量为1的有向边,跑最小割。 考虑一组割,一定将原图划分成源点和汇点两部分,那么左半部分都选0,右半部分都选1,那么它的代价就是割的代价,即要求最小割。 为了让点的值最小, 阅读全文
posted @ 2019-07-28 10:39 PYWBKTDA 阅读(182) 评论(0) 推荐(0) 编辑
摘要:如果没有换根操作,可以直接用树剖维护,考虑修改操作与根无关,所以只需要特殊处理查询操作。 对于查询操作,假设查询点为x,初始的根是1,实际的根是r,一共要分三种情况来考虑:1. 若lca(r,x)!=x或x=r,则直接对以x为根的子树查询即可; 2. 若lca(r,x)=x且x!=r,则对整棵树除了 阅读全文
posted @ 2019-07-28 10:38 PYWBKTDA 阅读(99) 评论(0) 推荐(0) 编辑
摘要:以x和y作为坐标建立kdtree,然后维护某一棵子树内的美味值之和,如果同一颗子树的四个角的甜味都小于h,那么就可以直接累加进去。虽然这样的最坏时间复杂度仍然是$o(n^{2})$,但可以卡过去。 1 #include<bits/stdc++.h> 2 using namespace std; 3 阅读全文
posted @ 2019-07-28 10:38 PYWBKTDA 阅读(118) 评论(0) 推荐(0) 编辑
摘要:预处理出每一个点下一个相同颜色的位置,记为next,然后将询问按左端点排序后不断右移左指针,设要删除i位置,就令f[next[next[i]]+1,同时还要删除原来的标记,即令f[next[i]]-1,最后即询问$\sum_{i=1}^{r}f[i]$,线段树维护即可。 1 #include<bit 阅读全文
posted @ 2019-07-28 10:38 PYWBKTDA 阅读(113) 评论(0) 推荐(0) 编辑
摘要:对于前两个sigma,可以直接处理,相当于求$\sum\limits_{1\leq i<j\leq n}lcp(i,j)$ 。 倒序字符串后的parent树(后缀树),lcp(i,j)其实就是i这个前缀和j这个前缀parent树上的lca,则对于任意一个节点,考虑其为lca的方案,就是任意两个儿子中 阅读全文
posted @ 2019-07-28 10:38 PYWBKTDA 阅读(108) 评论(0) 推荐(0) 编辑
摘要:1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 10000001 4 int t,n,m,k,mu[N],vis[N],p[N]; 5 long long ans,f[N]; 6 void linear(){ 7 mu[1]= 阅读全文
posted @ 2019-07-28 10:38 PYWBKTDA 阅读(69) 评论(0) 推荐(0) 编辑
摘要:首先对于询问操作可以使用可持久化线段树来维护,对于连边操作对于两颗树中选取较小的树暴力练到另一个点上,点数可以用并查集然后只修改根的点数即可。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mid (l+r>>1) 4 #def 阅读全文
posted @ 2019-07-28 10:38 PYWBKTDA 阅读(155) 评论(0) 推荐(0) 编辑
摘要:对于P*Q的矩形中每一个点挂一条长度为R的链,流量分别是下一个点的点权(链尾是inf),然后对于每一个点连向四周的后D个点连一条inf的边。 考虑最小割,当割掉某一条链的一条边,就表示选择该边,那么如果割掉的两条边相差大于D,那么一定可以顺着在前面的那个点走到另一条路上在走到汇点,不是满足条件的割。 阅读全文
posted @ 2019-07-28 10:38 PYWBKTDA 阅读(91) 评论(0) 推荐(0) 编辑
摘要:1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mod 1000000007 4 #define N 500005 5 #define ll long long 6 ll n,m,t,ans,mu[N],vis[N],p[N],c 阅读全文
posted @ 2019-07-28 10:37 PYWBKTDA 阅读(132) 评论(0) 推荐(0) 编辑
摘要:这道题有一种较为暴力的做法,对于每个点枚举所有与r2为该属性的询问并加以修改,最坏时间复杂度为o(nq),然而是可过的(97s) 发现只有当r2相同的询问数特别多时才会达到最坏时间复杂度,因此如果删除重复询问,时间复杂度降为o(nr),然而并没有显著优化(81s) 接着考虑当同一种r2的询问特别多时 阅读全文
posted @ 2019-07-28 10:37 PYWBKTDA 阅读(180) 评论(0) 推荐(0) 编辑
摘要:询问可以理解为将所有l~r的节点到根的路径都打上+1标记,然后询问相当于查询z到根的路径中有多少+1标记,这个问题可以转化为前缀和离线处理,用树链剖分套线段树维护。 还有一种分块的做法,对于每一个节点预处理出其到每一个块的答案,对于每一个块,可以发现f[k]=f[fa]+sz[k],其中sz[k]表 阅读全文
posted @ 2019-07-28 10:37 PYWBKTDA 阅读(86) 评论(0) 推荐(0) 编辑
摘要:离线读入并按照困难度排序,即相当于支持两种操作:连边和查询。对于每一个连通块在根节点建一个权值线段树,连边即合并两颗线段树,而查询就是在一棵线段树中查询(注意:边数和询问为$5*10^{5}$)。 1 #include<bits/stdc++.h> 2 using namespace std; 3 阅读全文
posted @ 2019-07-28 10:37 PYWBKTDA 阅读(94) 评论(0) 推荐(0) 编辑
摘要:暴力枚举两个数字并判定,如果不能同时选就连边,然后即求最大带权独立集。 普通图的最大带权独立集无法快速求出,但发现两个奇数一定无法使得1式成立(考虑模8,奇数平方模8为1,偶数平方模8为0或4),两个偶数一定无法使2式成立,因此奇数和偶数内部没有边,即形成了一张二分图。 首先假设所有数都可以选,考虑 阅读全文
posted @ 2019-07-28 10:37 PYWBKTDA 阅读(96) 评论(0) 推荐(0) 编辑
摘要:假设没有同时选文理科的收益,可以先将所有点的文理科收益都加起来,考虑最少要删掉多少收益,源点连向每一个点文科的收益,每一个点向汇点流理科的收益,然后每一条路径都最小割,即去掉了较小的收益。 但还有同时选同一种科目的收益,同样先加上所有选同种科目的收益,然后对于点(i,j),新增k1和k2两个点,源点 阅读全文
posted @ 2019-07-28 10:36 PYWBKTDA 阅读(161) 评论(0) 推荐(0) 编辑
摘要:首先将0变为-1,平衡的路径即该路径边权和为0,然后统计过重心且满足条件的路径数。 不断将统计当前这颗子树到之前所有子树的路径并合并,统计时,需要处理出两个桶a[i][j]和b[i][j],表示之前的子树/当前子树深度为i,到重心的路径中有(j=1)/没有(j=0)深度为0的节点(不能是根或本身)的 阅读全文
posted @ 2019-07-28 10:36 PYWBKTDA 阅读(131) 评论(0) 推荐(0) 编辑
摘要:发现a是c的祖先,b是c的祖先,则a和b也一定是祖先关系。 a已经确定了,考虑b:1.若a是b的祖先,考虑a中每一个节点作为c的方案数,显然就是min(d[x]-d[a]-1,k),其中x!=a且在a的子树中;2.若b是a的祖先,很好处理,即min(d[a],k)*(sz[a]-1)(深度从0开始) 阅读全文
posted @ 2019-07-28 10:36 PYWBKTDA 阅读(170) 评论(0) 推荐(0) 编辑
摘要:这道题还有一种分块的做法:每当发现当前子树中有K个点,就将这K个点合在一起,然后把每个块内的节点权值排序(虽然这个算法并没有保证块的个数,但是由于数(shen)据(qi)随(hai)机(luo),所以不妨设为n/K)。 操作0:对于每一个块暴力查询(构建一颗虚树),然后对根所在块暴力,时间复杂度o( 阅读全文
posted @ 2019-07-28 10:36 PYWBKTDA 阅读(79) 评论(0) 推荐(0) 编辑
摘要:发现任意两个点的连边都是一棵从从叶子节点搜索出来的trie树的一段,那么可以对所有trie树建立一个广义后缀自动机即求该后缀自动机的字符串数量,同bzoj4516。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 阅读全文
posted @ 2019-07-28 10:36 PYWBKTDA 阅读(82) 评论(0) 推荐(0) 编辑
摘要:首先计算出s数组,s表示可以重复的前缀等于后缀的个数,显然有s[i]=s[next[i]]+1,因为有且仅有next的next满足这个条件。 然后直接暴力枚举所有next,直到它小于i的一半,这个时间复杂度就是o(n)的 1 #include<bits/stdc++.h> 2 using names 阅读全文
posted @ 2019-07-28 10:36 PYWBKTDA 阅读(135) 评论(0) 推荐(0) 编辑
摘要:如果暴力dp的话时间复杂度为$o(n\sum_{i=1}^{n}ai)$,约为20亿。但显然我们对于f[i]只需要存储出现个数是奇数还是偶数就行了,即一个0/1。然后我们发现这只需要一个bitset就可以了,时间复杂度除以32,就可以过了。 1 #include<bits/stdc++.h> 2 u 阅读全文
posted @ 2019-07-28 10:36 PYWBKTDA 阅读(87) 评论(0) 推荐(0) 编辑
摘要:建立后缀自动机,对于一个节点,根据len排序后依次统计(t为0时每一个点只有1的贡献,t为1时每个点有|right|的贡献)子树内的子串数量,然后不断确定字符即可。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 500005 阅读全文
posted @ 2019-07-28 10:35 PYWBKTDA 阅读(145) 评论(0) 推荐(0) 编辑
摘要:dfs序(注意出栈时也要加入),然后对于每一次一个节点的修改,都在左端点上打+x,右端点上打-x,区间修改同理(因此要用线段树且需要维护区间左端点数量-右端点数量)。对于询问操作,就是dfs序上的一段前缀和,用线段树处理即可。 1 #include<cstdio> 2 #include<cstrin 阅读全文
posted @ 2019-07-28 10:35 PYWBKTDA 阅读(140) 评论(0) 推荐(0) 编辑
摘要:1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 50005 4 long long n,m,ans,mu[N],f[N],t[N],vis[N],p[N]; 5 void xxs(int n){ 6 mu[1]=f[1]=1; 阅读全文
posted @ 2019-07-28 10:35 PYWBKTDA 阅读(67) 评论(0) 推荐(0) 编辑
摘要:1 #include<bits/stdc++.h> 2 #include<tr1/unordered_map> 3 using namespace std; 4 #define ll long long 5 #define N 5000005 6 int t,n,mu[N],vis[N],p[N]; 阅读全文
posted @ 2019-07-28 10:35 PYWBKTDA 阅读(88) 评论(0) 推荐(0) 编辑
摘要:每一个区间相当于对[x,n]新增一个p,对[y+1,n]减少一个p,那么建立一棵可持久化线段树,然后对于修改第p个位置,同时统计出子树的点数和所有的和,类似于二分确定即可。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 20 阅读全文
posted @ 2019-07-28 10:35 PYWBKTDA 阅读(124) 评论(0) 推荐(0) 编辑
摘要:首先定义状态f[i][j]表示长度为i的串以j为结尾有多少符合条件的串,发现$f[i][j]=\sum f[i-1][k]$(j和k可以相邻),这个用矩阵乘法优化一下即可。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll l 阅读全文
posted @ 2019-07-28 10:34 PYWBKTDA 阅读(153) 评论(0) 推荐(0) 编辑
摘要:二分枚举答案,问题转化为计算至少取到一定体积,价格最少是多少,显然是贪心取最小,用线段树维护,然后因为要判断答案,所以可持久化一下即可。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define mid 阅读全文
posted @ 2019-07-28 10:34 PYWBKTDA 阅读(72) 评论(0) 推荐(0) 编辑
摘要:维护两颗可持久化字典树(当然可以放在一起),第一棵维护每一个点到根的每一位的二进制数量,在其父亲的基础上建立;第二棵维护dfs序上每一个点到第1个点的二进制数量,在其上一个点的基础上建立。 对于询问1,在第二棵上询问该子树对应区间;对于询问2,拆成x~lca和lca~y两段询问,询问时直接贪心即可。 阅读全文
posted @ 2019-07-28 10:34 PYWBKTDA 阅读(94) 评论(0) 推荐(0) 编辑
摘要:首先考虑没有深度限制,即对一颗子树求颜色数,那么可以用树上差分,根据dfs序,每个点和这个颜色在dfs中上一次出现点的lca打-1,然后每个点再打上一个+1,然后求一颗子树内所有节点的标记和即为答案。 为了深度限制,因此可以以深度为时间建一棵可持久化线段树,然后查询(x,d)即查询第deep[x]+ 阅读全文
posted @ 2019-07-28 10:34 PYWBKTDA 阅读(190) 评论(0) 推荐(0) 编辑
摘要:建立后缀树(即反序插入字符串的parent树),然后可以发现按照dfs序排列满足其反串按字典序从小到大排列,那么就可以维护出每一刻子树的串长和,然后直接在dfs序上二分确定节点,再在节点内部乱搞即可求出答案。 1 #include<bits/stdc++.h> 2 using namespace s 阅读全文
posted @ 2019-07-28 10:33 PYWBKTDA 阅读(189) 评论(0) 推荐(0) 编辑
摘要:状态f[i][j][k][l]表示前i个数,四种数的最后一次出现的位置分别是i、j、k和l(i>j>k>l),判断所有第右端点为i的区间是否满足此要求(不满足重置为0),考虑第i+1个位置填什么,转移到下一个位置上即可。 这样的时间复杂度看似是$o(Tn^{4})$,实际上由于枚举只需要比上一个数小 阅读全文
posted @ 2019-07-28 10:33 PYWBKTDA 阅读(113) 评论(0) 推荐(0) 编辑
摘要:记可乐为1,汉堡为-1,即求过程中绝对值不超过k的最短路。 然后发现k的范围仅为10,也就是说过程中合法的值仅有21种,因此跑一遍dij或spfa(嘿嘿嘿)即可。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pi pair<i 阅读全文
posted @ 2019-07-28 10:33 PYWBKTDA 阅读(160) 评论(0) 推荐(0) 编辑
摘要:显然答案可以理解为有(不是仅有)0对情况-1对情况+2对情况…… 考虑这个怎么计算,先计算这t对情况的位置,有c(n-3t,t)种情况(可以理解为将这4个点缩为1个,然后再从中选t个位置),然后相当于在剩下n-4t的位置上摆上4种东西,且每种东西有数量限制(ai-t个)。 这个东西dp一下即可,用f 阅读全文
posted @ 2019-07-28 10:33 PYWBKTDA 阅读(171) 评论(0) 推荐(0) 编辑
摘要:考虑我的每一次添加操作,要满足:1.该串是t的子串;2.该串不能与下一次的串开头字母构成t的子串。那么,设f[i][j][k]表示拼i次,第i次填入的开头字母是j,第i+1填入的开头字母是k的最短长度。 状态转移方程:f[i][j][k]=min(f[i-1][j][t]+f[1][t][k]),这 阅读全文
posted @ 2019-07-28 10:32 PYWBKTDA 阅读(177) 评论(0) 推荐(1) 编辑
摘要:假设该矩形是aij,那么有a(i,j)=a(i-1,j-1)^a(i-1,j+1)^a(i-2,j),不断递归下去可以发现a(i,j)=a(1,y-x+1)^a(1,y-x+3)^……^a(1,x+y-1)。 那么,对第一行处理前缀和,Si=S(i-2)^a(1,i),即给出了两个数S的异或,只需将 阅读全文
posted @ 2019-07-28 10:32 PYWBKTDA 阅读(192) 评论(0) 推荐(0) 编辑
摘要:对树长链剖分,dp令f[i][j]表示第i个点为根的子树中第j种颜色的数量,直接暴力dfs,对于每个节点,先dfs重儿子并直接继承重儿子的信息,再搜索轻儿子并合并,这样的时间复杂度是$o(nlog_{2}n)$的(当然好像直接不按顺序暴力合并也可以过,数据比较水)。 1 #include<cstdi 阅读全文
posted @ 2019-07-28 10:32 PYWBKTDA 阅读(94) 评论(0) 推荐(0) 编辑
摘要:题意可以理解为加边使原图变为完全图后不含有偶环的方案数(边权为0或1),可以联想到二分图染色,询问完全图的方案数即询问对于每一个点可以选0或1,然后使得1边连接的两点点权相同,0边连接的两点点权不同。 对于第一个联通块,显然已经确定,然后从第一个联通块向每一个联通块中的某一点连0边或1边都可以确定该 阅读全文
posted @ 2019-07-28 10:32 PYWBKTDA 阅读(218) 评论(0) 推荐(0) 编辑
摘要:不断将统计当前这颗子树到之前所有子树的路径并合并,考虑以前的路径为x,当前的路径为y,最终答案即$x\cdot 10^{len(y)}\equiv 0(mod\ p)$,转化为$x\equiv -y/10^{len(y)}(mod\ p)$,对于当前每一个y,查询之前x的个数(用map)即可,注意顺 阅读全文
posted @ 2019-07-28 10:31 PYWBKTDA 阅读(211) 评论(0) 推荐(0) 编辑
摘要:先树链剖分,开一棵线段树维护区间:1.abs的和;2.正数的数量-负数的数量;3.最大的负数。 询问就可以直接处理,考虑修改操作,对于一个区间,如果最大的负数+d变为了正数,就暴力修改下去,否则直接修改1和3两个信息并打上懒标记。因为d是非负的,所以每一个节点最多修改一次,时间复杂度不变。 1 #i 阅读全文
posted @ 2019-07-28 10:31 PYWBKTDA 阅读(119) 评论(0) 推荐(0) 编辑
摘要:显然可以写可持久化树套树,然而实际上由于只有一整行的修改和单点修改,并没有一个小矩形的修改,所以可以将其转化到一个序列上,只需要写可持久化线段树就可以了(然而标算是操作树)。 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 阅读全文
posted @ 2019-07-28 10:31 PYWBKTDA 阅读(142) 评论(0) 推荐(0) 编辑
摘要:考虑对询问分块,对于i<K的询问,暴力处理,时间复杂度为o(Kn);对于i>K的询问,发现答案都小于n/K且满足单调性,那么可以二分出每一段相同的答案,时间复杂度为$o(n^{2}log_{2}n/K)$,取K=1000可以通过。 1 #include<bits/stdc++.h> 2 using 阅读全文
posted @ 2019-07-28 10:30 PYWBKTDA 阅读(208) 评论(0) 推荐(0) 编辑
摘要:不管是否使用技能,发现操作前后所有堆二进制中1的个数之和不变。那么对于一个堆其实可以等价转换为一个k个石子的堆(k为该数二进制的个数),然后就是个nim游戏。 1 #include<bits/stdc++.h> 2 using namespace std; 3 int t,n,ans,a[101]; 阅读全文
posted @ 2019-07-28 10:30 PYWBKTDA 阅读(104) 评论(0) 推荐(0) 编辑
摘要:首先由一个神奇的序列叫做Purfer序列,他可以表示一棵树,且每个节点出现此时为度数-1(因此总长为n-2)。 然后dp,用f[i][j][k]表示用前i个点中的j个点构成了一个长度为k的Purfer序列(当然要符合条件),那么有$f[i][j][k]=f[i-1][j][k]+\sum\limit 阅读全文
posted @ 2019-07-28 10:29 PYWBKTDA 阅读(112) 评论(0) 推荐(0) 编辑
摘要:可以发现如果将根的结果写成多项式,可以发现只需要预处理出f[i][j]表示以i为根的子树j次项有多少个,g[i]表示从n个数中选取i个数相乘的和,就可以通过\sum_{i=1}^{n}f[1][i]\cdot g[i]\cdot (n-i)!$计算。可以发现有递推式:$g[i]=g[i-1]\cdo 阅读全文
posted @ 2019-07-28 10:28 PYWBKTDA 阅读(127) 评论(0) 推荐(0) 编辑
摘要:首先发现结果与需要改变的具体位置无关,只和需要改变的位置的个数有关,因此设f[i][j]表示选取了i个数字异或结果有j个1,只要分析接下来选择的数和这j个1有几个重合即可: 1. 三个数字全部重合,即$f[i][j+3]+=f[i-1][j]\cdot c(n-j,3)$ 2. 有两个数字重合,即$ 阅读全文
posted @ 2019-07-28 10:28 PYWBKTDA 阅读(109) 评论(0) 推荐(0) 编辑
摘要:1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mod 1000000007 4 #define N 1000005 5 long long n,ans,mu[N],f[N],t[N],vis[N],p[N]; 6 void xx 阅读全文
posted @ 2019-07-28 10:28 PYWBKTDA 阅读(138) 评论(0) 推荐(0) 编辑
摘要:首先有SG(x,y)=mex(SG(x-a,y-a),SG(x-a,y),SG(x,y-a)),其中SG(0,0)=0,打表发现(1,2)(3,5)(4,7)(6,10)(8,13)……时SG为0(即必败),假设第一项是ai,第二项是bi,很容易发现:1.bi=ai+i,2.ai=mex(bi,bj 阅读全文
posted @ 2019-07-28 10:28 PYWBKTDA 阅读(115) 评论(0) 推荐(0) 编辑
摘要:根据SG函数定义,可以发现当y<x<2y时,SG(x,y)=[SG(x-y,y)=0],即两者一定存在一个0,因此就有SG(x+ky,y)=mex(0,……)>0。 换句话来说,对于一个状态SG(x,y)(x>y),如果$x\ge 2y$即为必胜状态,而当x<2y时直接继续判断SG(x-y,y)这个 阅读全文
posted @ 2019-07-28 10:28 PYWBKTDA 阅读(82) 评论(0) 推荐(0) 编辑
摘要:建立后缀自动机,对于同一个节点,出现次数是相同的(right的大小),同时满足单调性(长度越长出现次数越少),所以只需要考虑最长的串即可。 PS:似乎也并不需要求依次后缀的max,不知道为什么…… 1 #include<bits/stdc++.h> 2 using namespace std; 3 阅读全文
posted @ 2019-07-28 10:27 PYWBKTDA 阅读(165) 评论(0) 推荐(0) 编辑
摘要:有两种方法,第一种直接KMP求出next数组,然后发现这样的重复一定是满足s[0,l)+s[l,r)+s[r,len),其中因为有s[0,l)=s[r,len),那么就有s[0,r)=s[l,len),又因为需要l尽量小,那么r就应该尽量大,即next[len]。 考虑如何判断next是否合法,仅需 阅读全文
posted @ 2019-07-28 10:27 PYWBKTDA 阅读(93) 评论(0) 推荐(0) 编辑
摘要:首先有SG(k)=mex(SG(k/2),SG(k/3)……SG(k/9)),SG(0)=0,通过打表可以发现当$n\in[1,1]\cup [10,18]\cup [163,324]……$,规律大概就是$[18^{k-1}+1,18^{k}/2]$时SG的值为0(即必败),那么只需要判断一下n是否 阅读全文
posted @ 2019-07-28 10:27 PYWBKTDA 阅读(75) 评论(0) 推荐(0) 编辑
摘要:求出后缀数组和height数组,然后二分答案后分组查询,一个块内如果有超过k个那么这个答案就可以。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 50005 4 int n,m,ans,a[N],b[N],h[N],sum[ 阅读全文
posted @ 2019-07-28 10:27 PYWBKTDA 阅读(80) 评论(0) 推荐(0) 编辑
摘要:最大团=反图的最大独立集,而反图又恰好是一张二分图,根据二分图的最大独立集=n-最大匹配就可以做了。 1 #include<cstdio> 2 #include<cstring> 3 #define N 405 4 struct ji{ 5 int nex,to; 6 }edge[N*N]; 7 i 阅读全文
posted @ 2019-07-28 10:26 PYWBKTDA 阅读(90) 评论(0) 推荐(0) 编辑
摘要:求出后缀数组和height数组,然后将这个串反过来写在前面然后枚举中心点并求两边的最长公共前缀即可(一定要加连接符)。 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 int n,m,ans,a[N],b[N 阅读全文
posted @ 2019-07-28 10:26 PYWBKTDA 阅读(102) 评论(0) 推荐(0) 编辑
摘要:求出后缀数组和height数组,然后因为子串即后缀的前缀,考虑不断新增后缀然后计算贡献,如果以sa的顺序新增那么第i个就会产生n-sa[k]+1-h[k](n-sa[k]+1为总方案,h为不合法的方案),累计即可。 1 #include<bits/stdc++.h> 2 using namespac 阅读全文
posted @ 2019-07-28 10:26 PYWBKTDA 阅读(86) 评论(0) 推荐(0) 编辑
摘要:考虑定义以下dp数组:1.g1[i][j]表示第i行从中间出发向左取j瓶牛奶最少要多久2.g2[i][j]表示第i行从中间出发向右取j瓶牛奶最少要多久3.g3[i][j]表示在g1[i][j]的基础上回到中间最少要多久4.g4[i][j]表示在g2[i][j]的基础上回到中间最少要多久5.f1[i] 阅读全文
posted @ 2019-07-28 10:26 PYWBKTDA 阅读(327) 评论(0) 推荐(0) 编辑