• bzoj 2726 [SDOI2012]任务安排(斜率DP+CDQ分治)


    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=2726

    【题意】

        将n个任务划分成若干个块,每一组Mi任务花费代价(T+sigma{ tj }+s)*sima{ fi },j属于Mi,T为当前时间,问最小代价。

    【思路】

        设f[i]为将前i个任务划分完成的最小费用,Ti Fi分别表示t和f的前缀和,则不难写出转移方程式:

            f[i]=min{ f[j]+(F[n]-F[j])*(T[i]-T[j]+s) },1<=j<=i-1

        经过整理得到:

            f[i]=min{ -T[i]*F[j]+(f[j]-F[n]*T[j]+F[j]*T[j]-s*F[j]) }

        设X(i)=F[i],Y(i)=f[j]-F[n]*T[j]+F[j]*T[j]-s*F[j],a(i)=T[i]则有:

            f[i]=min{ -a(i)*X(j)+Y(j) }

        则我们需要:

            min p = -a(i)*X(j)+Y(j)

        即最小化直线方程:Y(j)=a(i)*X(j)+p的截距。

        如果时间没有负数的话(出题人神脑洞<_<,这个题可以直接上单调队列维护下凸线。事实上这个算法可以得到60分。

        有了负数以后因为斜率不满足随x单调,所以不能使用单调队列。

        然后这道题就需要用splay或CDQ分治解。

        Splay写法还是不会=-=,CDQ分治的处理和 这道题 类似,就不再赘述了。

        需要注意的:x,y可能到达long long级别,所以不要直接除得slop

            运算过程中long long的标识。

            归并数组的时候几个小条件。

    【代码】

      1 #include<set>
      2 #include<cmath>
      3 #include<queue>
      4 #include<vector>
      5 #include<cstdio>
      6 #include<cstring>
      7 #include<iostream>
      8 #include<algorithm>
      9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
     10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     11 #define rep(a,b,c) for(int a=(b);a>=(c);a--)
     12 using namespace std;
     13 
     14 typedef long long ll;
     15 const int N = 5e5+10;
     16 const ll inf = 1e18;
     17 
     18 ll read() {
     19     char c=getchar();
     20     ll f=1,x=0;
     21     while(!isdigit(c)) {
     22         if(c=='-') f=-1; c=getchar();
     23     }
     24     while(isdigit(c))
     25         x=x*10+c-'0',c=getchar();
     26     return x*f;
     27 }
     28 
     29 struct Pt 
     30 {
     31     ll x,y,k;
     32     int id;
     33     bool operator < (const Pt& rhs) const 
     34     {
     35         return k<rhs.k;
     36     }
     37 }q[N],t[N];
     38 
     39 bool cmp(const Pt& a,const Pt& b)
     40 {
     41     return a.x<b.x || a.x==b.x&&a.y<b.y;
     42 }
     43 
     44 int T[N],F[N],st[N],top,n,s; ll f[N];
     45 
     46 ll U(int j,int k)
     47 {
     48     return (ll)q[k].y-q[j].y;
     49 }
     50 ll D(int j,int k)
     51 {
     52     return (ll)q[k].x-q[j].x;
     53 }
     54 
     55 void solve(int l,int r)
     56 {
     57     if(l==r) {
     58         q[l].x=(ll)F[l];
     59         q[l].y=(ll)f[l]-(ll)F[n]*T[l]+(ll)F[l]*T[l]-(ll)s*F[l];
     60         return ;
     61     }
     62     int mid=l+r>>1;
     63     int l1=l,l2=mid+1;
     64     FOR(i,l,r) {
     65         if(q[i].id>mid) t[l2++]=q[i];
     66         else t[l1++]=q[i];
     67     }
     68     memcpy(q+l,t+l,sizeof(Pt)*(r-l+1));
     69     solve(l,mid);
     70     top=0;
     71     FOR(i,l,mid) {
     72         while(top>1 && (ll)U(st[top-1],st[top])*D(st[top-1],i)>(ll)U(st[top-1],i)*D(st[top-1],st[top])) top--;
     73         st[++top]=i;
     74     }
     75     int j=1;
     76     FOR(i,mid+1,r) {
     77         while(j<top && U(st[j],st[j+1])<(ll)q[i].k*D(st[j],st[j+1])) j++;
     78         f[q[i].id]=min(f[q[i].id],-(ll)q[i].k*q[st[j]].x+q[st[j]].y+(ll)F[n]*(T[q[i].id]+s));
     79     }
     80     solve(mid+1,r);
     81     l1=l,l2=mid+1;
     82     FOR(i,l,r) {
     83         if((l2>r||cmp(q[l1],q[l2]))&&l1<=mid) t[i]=q[l1++];
     84         else t[i]=q[l2++];
     85     }
     86     memcpy(q+l,t+l,sizeof(Pt)*(r-l+1));
     87 }
     88 
     89 int main()
     90 {
     91 //    freopen("in.in","r",stdin);
     92 //    freopen("out.out","w",stdout);
     93     n=read(),s=read();
     94     FOR(i,1,n)
     95         T[i]=read(),T[i]+=T[i-1],
     96         F[i]=read(),F[i]+=F[i-1];
     97     FOR(i,1,n) {
     98         q[i].id=i;
     99         q[i].k=T[i];
    100         f[i]=inf;
    101     }
    102     sort(q+1,q+n+1);
    103     solve(0,n);
    104     printf("%lld
    ",f[n]);
    105     return 0;
    106 }

    简单DP(20分)

     1 #include<set>
     2 #include<cmath>
     3 #include<queue>
     4 #include<vector>
     5 #include<cstdio>
     6 #include<cstring>
     7 #include<iostream>
     8 #include<algorithm>
     9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
    10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
    11 #define rep(a,b,c) for(int a=(b);a>=(c);a--)
    12 using namespace std;
    13 
    14 typedef long long ll;
    15 const int N = 2e5+10;
    16 const ll inf = 1e18+10;
    17 
    18 ll read() {
    19     char c=getchar();
    20     ll f=1,x=0;
    21     while(!isdigit(c)) {
    22         if(c=='-') f=-1; c=getchar();
    23     }
    24     while(isdigit(c))
    25         x=x*10+c-'0',c=getchar();
    26     return x*f;
    27 }
    28 
    29 ll T[N],F[N],f[N],pre[N],n,s;
    30 
    31 int main()
    32 {
    33     freopen("in.in","r",stdin);
    34     freopen("outr.out","w",stdout);
    35     n=read(),s=read();
    36     FOR(i,1,n) 
    37         T[i]=read(),T[i]+=T[i-1],F[i]=read(),F[i]+=F[i-1]    ;
    38     FOR(i,1,n) {
    39         f[i]=inf;
    40         FOR(j,0,i-1) {
    41             //f[i]=min(f[i],f[j]+(F[n]-F[j])*(T[i]-T[j]+s));
    42             int tmp=-T[i]*F[j]+(f[j]-F[n]*T[j]+F[j]*T[j]-s*F[j]);
    43             if(tmp<f[i]) pre[i]=j,f[i]=tmp;
    44         }
    45         f[i]+=F[n]*(T[i]+s);
    46     }
    47     printf("%lld
    ",f[n]);
    48     //FOR(i,1,n) {
    49     //    printf("%d %d
    ",F[i],f[i]-F[n]*T[i]+F[i]*T[i]-s*F[i]);
    50     //}
    51     return 0;
    52 }
    View Code
  • 相关阅读:
    Mac 安装实用开发软件和日常软件清单
    Docker zabbix-agent 监控 docker tomcat 多实例
    zabbix 组件监控概述
    实况8操作指南
    关于哲哲跳舞这件小事儿
    左耳听风笔记摘要(11-12)程序的异常处理
    左耳听风笔记摘要(07-10)推荐书单/Go/Docker
    从零开始的vue学习笔记(一)
    简述Spark工作流程
    opengl简单入门实例
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5362036.html
Copyright © 2020-2023  润新知