摘要:
考虑根号分治。设 \(m=\sum k_i\),则把 \(k>\sqrt m\) 的称为大集合,\(k\leq \sqrt m\) 的称为小集合。 对于小集合与小集合: 暴力枚举每个集合的每一对 \((x,y)\),开一个哈希表维护有没有其他的集合也存在这个数对。由于集合大小不超过 \(\sqrt 阅读全文
摘要:
首先可以写出这样一个方程 \[ dp_i=\max_{j<i,a_j\leq a_i}\{dp_j+1+w(i,j)\} \] 其中,\(w(i,j)=0/1\) 表示 \([i+1,j-1]\) 有没有比 \(a_i\) 和 \(a_j\) 都大的数。 考虑维护每个点的 \(pre\) 表示 \( 阅读全文
摘要:
每次删数都会删恰好 \(k-1\) 个,所以删的数总个数必须是 \(k-1\) 的倍数。考虑最终状态,如果所有数左边不足 \(\frac{k-1}{2}\) 个删掉的数或右边不足 \(\frac{k-1}{2}\) 个删掉的数,那么最后一步是无法实现的。否则,实现了最后一步之后,就可以很轻松的实现前 阅读全文
摘要:
注意到只要两个人初始的朝向相反就可以看到对方,否则不行。直接把斜率搞成一个 pair 压到 map 里存个数就行了。 点击查看代码 #include<cstdio> #include<iostream> #include<map> #define mp std::make_pair typedef 阅读全文
摘要:
首先有一个结论,每个人向前走只会走 \(1\) 格,走更多不会更优。感觉应该是挺好证的。然后接下来就可以考虑 dp,设 \(dp_i\) 表示搞完了 \([1,i]\) 的所有 boss,现在在 \(i+1\) 位置的最小时间。有三种转移: 用手枪一个一个打小怪,用狙击枪打boss,走到下一关 用手 阅读全文
摘要:
考虑不论怎么样,每个子树里边最长的链都会接在别的链下面,因为如果这条链不动,让别的链接过来一定不优。所以就直接按这个排序然后输出 dfs 序就行了。具体证明我也不会,就是考场猜了个结论。 点击查看代码 const int N=1e5+13; int n,son[N],maxd[N],dfn[N],d 阅读全文
摘要:
一般这种 dp 的转移都是相邻格子之间的,但是这道题相邻格子之间转移没办法搞掉题目的这个限制。考虑每次转向的时候转移,这样对于某一个点,他能转移的一定是一个区间(不能到最后 \(cnt\) 个,那样就把石头推出去了)。暴力做是 \(O(n^3)\) 的,区间的这个可以前缀和优化,就 \(O(n^2) 阅读全文
摘要:
如果没有敌对关系,枚举一共选 \(i\) 个人,如果有 \(j\) 个人满足 \(i\in [l_j,r_j]\),那么方案数是 \(\binom{i}{j}\)。 接下来考虑限制,由于 \(m\leq 20\),考虑容斥,直接钦定一个集合 \(S\),其中所有为 \(1\) 的位置对应的限制必选, 阅读全文
摘要:
考虑一个分治:每次如果要用第一种,一定是给整个区间用,直到没有办法覆盖整个区间,用的次数是 \(\min_{i=L}^R a_i\) 次,减去它之后分别递归最小值的两边。注意到如果某一次不使用第一个操作,那么以后也都不会用了,此时操作总数就是不为 \(0\) 的位置个数。复杂度最慢也是 \(O(n^ 阅读全文
摘要:
首先,抽到一次鬼牌视作一次迭代,那么每次迭代的期望长度是一样的,即 \[ \begin{aligned} E(x)&=1\times\frac{m}{n+m}+2\times\frac{n}{n+m}\times\frac{m}{n+m-1}+\ldots+(n+1)\times(\prod_{j= 阅读全文
摘要:
考虑如果把同样的一段操作序列同时给两个串做,对答案是没有影响的。所以考虑把每个区间差分成后缀(不能是前缀,因为这样相同的操作序列在前面没法抵消),这样就可以表示区间了。两个串分别的对每个后缀操作之后得到的串可以 \(O(nk)\) 算出来,就是记录每个位置最终会被换到哪里就可以从右向左递推。 算出两 阅读全文
摘要:
由于一开始的序列中没有两个相同的 \(h\),猜测最终的序列中 \(h_i=h_{i+1}\) 的位置最多只有一个。大概可以这样感性理解:考虑从左到右做“滑坡”,如果之前 \(h_i=h_{i-1}\),那么后面要么 \(h\) 都不相同,要么有一个位置相同了会带动一段都 \(+1\),导致 \(h 阅读全文
摘要:
一共会走 \(2n-2\) 步,那么钦定第 \(i\) 步向右 \(\Rightarrow\) 和的第 \(i\) 位为 \(1\),向下为 \(0\)。考虑如何构造出满足这个条件的矩阵:假设当前位置 \((i,j)\) 从右下到左上位于第 \(k\) 条斜线,那么这个位置为 \((j-1)(2^k 阅读全文
摘要:
设 \(c_i=0/1\) 表示 \(i\) 有没有在 \(a\) 中出现,那么这个就是他自己和自己的差卷积,卷出来之后不是 \(0\) 的位置就都可以,每个可以的位置更新一下自己的倍数就行(或者使用狄利克雷前缀和,不过暴力做复杂度也过得去)。 差卷积就翻一下序列然后 FFT 就行了。 点击查看代码 阅读全文
摘要:
如果当前有 \(sum\) 个可以翻倍,那么考虑可不可以让前 \(sum\) 大的都翻倍。可以当且仅当这 \(sum\) 大的数不全能翻倍下一个数。如果全都能翻倍下一个数,那只能牺牲第 \(sum\) 大的数,最后可以再翻倍一个第 \(sum+1\) 大的。 然后有多次删除插入就用 set 维护一下 阅读全文
摘要:
把贡献看成边,那么会形成一个树形结构。有一个做法就是在树上做 dp 然后树状数组优化,\(O(n^2\log n)\)。 我的做法是,考虑一个区间 dp,设 \(f_{l,r}\) 表示所有在 \([l,r]\) 内的线段最多选多少个,这样就有一个 \(O(n^3)\) 的 dp。考虑什么情况的转移 阅读全文
摘要:
对于两种权值的分别贪心维护,最后枚举一种权值选多少个,另一个二分出来,总复杂度 \(2\log\)。 点击查看代码 #include<cstdio> #include<iostream> #include<queue> typedef long long ll; inline int min(con 阅读全文