zoukankan      html  css  js  c++  java
  • Print Article(斜率DP入门+单调队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3507

    题目大意:给你n个数,然后问你怎么分割当前的这n个数位那几组,使得每一组的权值加起来最大。每一组权值的计算方法在题目上说了。

    具体思路: 一开始打了一波两重for循环的,一直求一个tile,但是wa了。然后就学了斜率优化的方法

    https://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html

    就是把表达式转换成斜率类型的表达式,然后对于当前的节点,通过判断斜率的方式来决定当前的点是不是该选择,这个过程可以用单调队列维护。

    AC代码:

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<cmath>
     4 using namespace std;
     5 # define ll long long
     6 const int maxn = 6e5+100;
     7 int sum[maxn];
     8 int q[maxn];
     9 int dp[maxn];
    10 int n,m;
    11 int getdp(int i,int j){
    12 return dp[i]+m+(sum[j]-sum[i])*(sum[j]-sum[i]);
    13 }
    14 int getup(int i,int j){
    15 return dp[i]+sum[i]*sum[i]-(dp[j]+sum[j]*sum[j]);
    16 }
    17 int getdown(int i,int j){
    18 return 2*(sum[i]-sum[j]);
    19 }
    20 int main(){
    21 while(~scanf("%d %d",&n,&m)){
    22 for(int i=1;i<=n;i++){
    23 scanf("%d",&sum[i]);
    24 sum[i]+=sum[i-1];
    25 }
    26 int tail,head;
    27 tail=head=0;
    28 q[tail++]=0;
    29 
    30 for(int i=1;i<=n;i++){
    31 while(head+1<tail&&getup(q[head+1],q[head])<=sum[i]*getdown(q[head+1],q[head]))head++;
    32 dp[i]=getdp(q[head],i);
    33 while(head+1<tail&&getdown(q[tail-2],q[tail-1])*getup(q[tail-1],i)<=getdown(q[tail-1],i)*getup(q[tail-2],q[tail-1]))tail--;
    34 q[tail++]=i;
    35 }
    36 printf("%d
    ",dp[n]);
    37 }
    38 return 0;
    39 }
  • 相关阅读:
    使用Apache的ab工具进行压力测试
    Effective Java开篇
    mysql删除同一表中重复字段记录
    正则表达式的元字符匹配
    几个学习git的地方
    创建和销毁对象
    遇到多个构造器参数时要考虑用构建器
    Java的类和接口
    转:流言粉碎机:每天对着电脑46小时的人必看
    页面选中文字弹出层,点击层中文字或者图片触发事件
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10558822.html
Copyright © 2011-2022 走看看