https://ac.nowcoder.com/acm/contest/881/I
不得不说这题是真的难,看题解都差点没用理解。)
给定平面上若干(1e5)点,每个点ab两个权值,要求将其分为两组,a组的a权值和加b组的b权值和最大,划分条件转化一下就是,不能有a出现在b的右下,也就是要找到一条不降的折线,其上是a,其下是b。我们认为位于折线上的那些点属于b。
暴力dp是可做的,离散化xy并枚举每一列的划分点。考虑优化,认为dp[i]表示,加入i点后,如果折线的最后一个转折点是i,那么总和的最大值。它该怎么更新呢,对于点1~i-1,如果它们比i低,那折线就可以从它们那里拐过来,然后再加上b[i];同时,再加入i点后,其余的dp值也需更新,比i高的折线会把i看作b,比i低的折线会把i看作a,分别加上这两个值即可。
这里我们注意到,已经用到了单点修改、区间加、询问区间最大值的操作,就果断线段树,将y离散化后在y上建立线段树,也就是dp数组是用线段树实现的。注意需要考虑x轴,这样一条会把所有点视为a的折线,建线段树的时候按1,1+tot范围去建立即可。
代码
1 | #include<bits/stdc++.h> |