国庆期间乱做的题
AGC038D
\(\mathtt{\color{red}{T},\color{green}{W}}\)
首先如果 \(a,b\) 只有一条路径,且 \(b,c\) 只有一条路径,那么 \(a,c\) 一定只有一条路径。显而易见的,\(a,c\) 之间的合法路径只能为 \(a\rightarrow b\rightarrow c\) 。因此将所有的由 \(0\) 类边连起来的点放在一起,形成一个联通块(显然只能是一棵树)。
假设有 \(k\) 个联通块,因为每个联通块都是一棵树,因此还剩下 \(m-n+k\) 条边。
如果这个时候没有 \(1\) 类边的话:
- 边数的最小取值:将 \(k\) 棵树连起来的边数花费为 \(k-1\) 。
- 边数的最大取值:比较显然的是因为同一联通块中的点不能属于一个环内,所以钦定每个联通块有一个"外交官"专门负责向外面连边,其他点都不能向外面连边。这样的话 \(k\) 个"外交官"可以随便连边,因此边数为 \(\frac{k(k-1)}{2}\) 。
如果有 \(1\) 类边:
- 如果只有两个联通块:想不出怎么构造了,无解。
- 如果有一条 \(1\) 类边的两个端点属于同一联通块:两个同一联通块的点不能放在一个环里面,无解。
- 边数的最小取值:将 \(k\) 个"外交官"连成一个环即可,边数为 \(k\) 。
- 边数的最大取值:同样是 \(\frac{k(k-1)}{2}\) 。
维护一下联通块,然后判断 \(m\) 是否在合法区间内即可。
ARC070D
\(\mathtt{\color{red}{T},\color{green}{W}}\)
当 \(b\geq a\) 的时候,不友好的人完全可以用一个大小为 \(a\) 的子集模仿诚实的人,这样无论如何都无法得到解。
考虑先找出一个诚实的人,然后用这个诚实的人依次检查所有的人。如何找这个诚实的人呢?
考虑到询问一对 x y
,如果答案为 NO
的话,意味着这两个人之间至少有一个不友好的人。这个时候将这两个人直接删掉仍然满足 \(a>b\) 。如果答案为 YES
,两人的身份有三种情况,不好判断,但是容易发现,将所有的 NO
二元组删掉后,剩下的所有人一定满足前一段是不友好的,后一段是诚实的,而且至少存在一个诚实的,因此遇到 YES
什么都不干就好了,最后剩下的这个序列取最后一个人即可,这个人必然是诚实的。
用栈维护整个操作即可。
不瞄题解做不出来 atcoder,难受 >_<
「HEOI2016/TJOI2016」排序
\(\mathtt{\color{green}{T},\color{green}{W}}\)
二分最终的答案,然后就可以将原序列变成 01
序列。
然后两个操作都变成了区间推平操作了,线段树维护即可。
「国家集训队」middle
\(\mathtt{\color{red}{T},\color{green}{W}}\)
主席树神题。
中位数的一个套路:转化成 01
序列。
问题就在于二分一个 \(mid\) 后,对于这个 01
序列,怎么求一个区间的前缀最大值和后缀最大值。
不妨考虑每一个 \(mid\) 都建一颗线段树维护对应 01
序列以及前缀最大值后缀最大值区间和等,不过空间开不下。但可以发现如果将 \(mid+1\) 的话只有一个位置发生了改变,因此可以将线段树替换为主席树维护。
「TJOI2015」棋盘
\(\mathtt{\color{green}{T},\color{red}{W}}\)
显然需要在意的只有第 \(i\) 行前两行的棋子状态。
这样列出 \(dp\) 后矩阵快速幂优化即可。
「SDOI2017」序列计数
\(\mathtt{\color{green}{T},\color{red}{W}}\)
考虑用所有方案数减去不合法方案数。
考虑不合法方案数怎么求,将所有合数按照 \(\pmod{p}\) 的结果分类,就可以得到 \(g(i)\) 表示选择一个模 \(p\) 后等于 \(i\) 的数的方案数。因为 \(p\) 很小,这样就可以直接矩阵快速幂了。
所有方案数一样也是直接矩阵快速幂好了。
ARC058E
\(\mathtt{\color{red}{T},\color{green}{W}}\)
\(5+7+5=17\) 十分小,考虑状压。
比方说 \(4,2\) 压成 \(010001\),\(1,5\) 压成 \(100001\) ,只压 \(17\) 位。第 \(k\) 位上有一相当于 \(i\) 有一段后缀的和为 \(k\),因此合法当且仅当 \(x+y+z,y+z,z\) 位上都有 \(1\) 。
令 \(dp(i,j)\) 表示前 \(i\) 个数不合法的方案数,且当前状态为 \(j\) 。转移的时候考虑下一个数选什么,得到目标状态后检查是否同时包含 \(x+y+z,y+z,z\) 三个位置即可。
最后的答案显然是 \(10^n-\sum dp(n,i)\) 。
int lim=(1<<(x+y+z))-1;
int res=(1<<(x+y+z-1))|(1<<(y+z-1))|(1<<(z-1));
dp[0][0]=1;
lep(i,1,n) lep(S,0,lim) lep(k,1,10) {
int T=((S<<k)|(1<<(k-1)))&lim;
if((T&res)!=res) pls(dp[i][T],dp[i-1][S]);
}