ZLOJ练习36
written on 2022-07-08
许多题都作为原题形式做过一模一样的,但竟然没有做出来!一道点分治,一道线段树合并,都很模板,真的很不应该!
\(A\) 题区间dp,虽然过了,但是状态设计得不好,可以直接看看代码回忆一下。
然后根据C题总结一下点分治的套路:这类题往往统计树上满足条件的点对的个数(或是寻找最优点对),一旦看到树上统计点对这样的类型,就可以考虑点分治了,平时记得多看看,不要忘了模板怎么打。
\(D\) 题考试时有点线段树合并的思路,但是考试的时候在一个点上卡住了。
为了计算两棵线段树对应集合的逆序对数(顺便在此过程合并),我们实际上采用了一点分治的思想,也就是分 \(3\) 类计算,前二者是左右子树内部的,后者是跨子树的,然后因为我们是递归合并线段树的,因此这恰好为分治提供了很好的载体,于是就有了这样的计算:
void merge(int &x,int y,int l,int r)
{
if(!x||!y)
{
x|=y;
return ;
}
ans1+=1ll*val[ls[x]]*val[rs[y]];//正序对
ans2+=1ll*val[rs[x]]*val[ls[y]];//逆序对
if(l==r)
{
val[x]+=val[y];
return ;
}
int mid=l+r>>1;
merge(ls[x],ls[y],l,mid),merge(rs[x],rs[y],mid+1,r);
val[x]=val[ls[x]]+val[rs[x]];
}
权当教训。