Loading

国庆期间乱做的题

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]);
}
posted @ 2020-10-10 15:26  Moonlightsqwq  阅读(135)  评论(0编辑  收藏  举报