今天的题正解还不算太难。
T1:网络流。
首先我们要求答案最大,那么就是总的减去损失的最大,也就是要求损失的最小(这才符合网络流模型)。
那么现在我们来分析损失:若一个a[i]=0,那么我们会损失所有的b[i][j]和b[j][i],而如果一个a[i]=1那么我们会损失一个c[i]的代价。
然后我们就构想出了一个图:
(忘了画箭头……将就一下吧)
对于每一个i、j都这么建,显然是对的。
但是这个会超时,所以我们需要优化建图:
我们对于每一对i、j这样来建图,这个也是对的,不理解的话手玩一下就会明白了。
最后我们把所有S连向i的b[j][i]都加起来,合成一条边,这样就建出了一个可以AC的图。
注意这个图要用dinic或者ISAP来跑,不能暴力增广。(dinic和ISAP详见“较优的网络流算法”)
T2:思维题。
先把所有点按x从小到大排序(注意是按x而不是y!!!)。
然后设f[i][0/1]表示当前到第i个点,它的下一个点在它的左边(0)或右边(1)的方案数。
接着枚举i=1~n,j=i-1~1.
若y[i]<y[j],那么f[j][1]+=f[i][0]+1
若y[i]>y[j],那么f[i][0]+=f[j][1]+1
至于为什么这样转移,我们首先看看选出的序列是长什么样子的:
然后我们发现如果一个点在它前面那个点的左侧,那么它的下一个点一定在它的右侧。反之亦然。
而且我们在dp时要按y从小到大的顺序转移,不然会因为后效性出错。
至于为什么要加1,这是因为除了之前的方案数以外,还可以多一个方案,就是当前点自成一个序列。
这题很巧妙,要好好理解。
T3:
首先我们设f[i]表示到i时的最大值,然后根据dfs序转移。
接着我们发现对于一个点能转移到它的点就是它往上第一个有左边兄弟祖先的左边兄弟往下形成的右链。(这个很绕,可以不看,自己画一下就明白了)。
然后我们又会发现一个点转移到别的点的次数不超过两次(因为要转移到别的点的话它就一定要在右链上),所以我们可以dfs枚举每一个点,然后找出转移到它的右链和它的左链,现在我们就要用转移到它的右链来求它的左链上的点的f值。而此时随着链上的点的深度的加深,max点权是单调不递减的,那么我们就可以通过枚举左链,从中间分开右链来转移了。