简要的做题记录?

AGC038D

(mathtt{color{red}{T},color{green}{W}})

首先如果 (a,b) 只有一条路径,且 (b,c) 只有一条路径,那么 (a,c) 一定只有一条路径。显而易见的,(a,c) 之间的合法路径只能为 (a ightarrow b ightarrow 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}})

(bgeq 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]);
}
原文地址:https://www.cnblogs.com/losermoonlights/p/13792877.html