左偏树
炒鸡棒的论文《左偏树的特点及其应用》
虽然题目要求比论文多了一个条件,但是……只需要求非递减就可以AC……数据好弱……
虽然还没想明白为什么,但是应该觉得应该是这样——求非递减用大顶堆,非递增小顶堆……
这题和bzoj1367题意差不多,但是那题求的是严格递增。(bzoj找不到那道题,可能是VIP或什么原因?
严格递增的方法就是每一个数字a[i]都要减去i,这样求得的b[i]也要再加i,保证了严格递增(为什么对我就不知道了
代码比较水,因为题目数据的问题,我的代码也就钻了空子,反正ac就好了。。。。
![](https://img7.php1.cn/3cdc5/f375/a6e/f714ef80399aa05d.gif)
![](https://img7.php1.cn/3cdc5/f375/a6e/1114b82b24632a82.gif)
#include
#include
#include
#include
using namespace std;const int N = 2005;
typedef long long ll;struct LTree {int l, r, sz;int key, dis;bool operator<(const LTree lt) const {return key < lt.key;}
} tr[N];
int cnt_tr;int NewTree(int k) {tr[&#43;&#43;cnt_tr].key &#61; k;tr[cnt_tr].l &#61; tr[cnt_tr].r &#61; tr[cnt_tr].dis &#61; 0;tr[cnt_tr].sz &#61; 1;return cnt_tr;
}int Merge(int x, int y) {if (!x || !y) return x &#43; y;if (tr[x] < tr[y]) swap(x, y);tr[x].r &#61; Merge(tr[x].r, y);if (tr[tr[x].l].dis < tr[tr[x].r].dis) swap(tr[x].l, tr[x].r);tr[x].dis &#61; tr[tr[x].r].dis &#43; 1;tr[x].sz &#61; tr[tr[x].l].sz &#43; tr[tr[x].r].sz &#43; 1;return x;
}int Top(int x) {return tr[x].key;
}void Pop(int &x) {x &#61; Merge(tr[x].l, tr[x].r);
}int a[N], root[N], num[N];int main() {int n;while (~scanf("%d",&n)) {ll sum, tmp, ans;cnt_tr &#61; sum &#61; tmp &#61; 0;for (int i &#61; 0; i
}
&#xff0d;&#xff0d;&#xff0d;&#xff0d;
考虑dp&#xff0c;dp[i][j]表示前i个数&#xff0c;最后一个数是j的最小花费
dp方程&#xff1a;dp[i][j]&#61;min(dp[i-1][k], k≤j) &#xff0b; abs(a[i]-j)
j的范围1e9&#xff0c;是因为对于每一个i来说&#xff0c;当最优解的时候j一定是a数列中的数&#xff0c;所以只需枚举a数列中的值就可以了。
容易想到dp[i-1][k]就不需要另外一层循环就了&#xff0c;同时可以使用滚动数组&#xff08;不使用明显也够
上面求的是不减&#xff0c;求不增把数组到倒过来就可以了。&#xff08;懒&#xff0c;没写。。
时间复杂度O(n^2)&#xff0c;比上面左偏树明显慢了不少。
![](https://img7.php1.cn/3cdc5/f375/a6e/f714ef80399aa05d.gif)
![](https://img7.php1.cn/3cdc5/f375/a6e/1114b82b24632a82.gif)
#include
#include
#include
#include
const int N &#61; 2005;
const int INF &#61; 0x5f5f5f5f;int dp[N][N];
int a[N], b[N];
int main() {//freopen("in", "r", stdin);int n;scanf("%d", &n);for (int i &#61; 1; i <&#61; n; &#43;&#43;i) {scanf("%d", a&#43;i);b[i] &#61; a[i];}sort(b&#43;1, b&#43;1&#43;n);int last;for (int i &#61; 1; i <&#61; n; &#43;&#43;i) {last &#61; INF;for (int j &#61; 1; j <&#61; n; &#43;&#43;j) {last &#61; min(last, dp[i-1][j]);dp[i][j] &#61; fabs(b[j]-a[i]) &#43; last;}}int ans &#61; INF;for (int i &#61; 1; i <&#61; n; &#43;&#43;i) {ans &#61; min(ans, dp[n][i]);}printf("%d\n", ans);return 0;
}
贪心
https://blog.csdn.net/lycheng1215/article/details/80089004
![](https://img7.php1.cn/3cdc5/f375/a6e/f714ef80399aa05d.gif)
![](https://img7.php1.cn/3cdc5/f375/a6e/1114b82b24632a82.gif)
#include
#include
#include
#include
using namespace std;const int maxn &#61; 2e5 &#43; 7;
int a[maxn];priority_queue<int>s;int main(int argc, char const *argv[])
{int n;scanf("%d", &n);long long ans &#61; 0;for(int i &#61; 1;i <&#61; n ; i &#43;&#43;) {scanf("%d", &a[i]);//a[i] -&#61; i;
s.push(a[i]);if(s.top() > a[i]){ans &#43;&#61; s.top() - a[i];s.pop();s.push(a[i]);}}printf("%d",ans);return 0;
}
单调递增严格就是将a[i] - i 跑 以上就行