7.10省队集训梦工厂

原创 2015年07月10日 15:23:06


思路:题面真心长....单调栈维护上凸壳即可

设sum[i]为前i道工序的复杂度之和,g[i]为第i个快乐最早开始生产的时间。因为我们要保证没有两个快乐同时出现在同一道工序,所以

g[i]=g[i-1]+max(sum[j]*f[i-1]-sum[j-1]*f[i])

然后就是像斜率优化的过程了

sum[j]*f[i-1]=f[i]*sum[j-1]+g[i]-g[i-1]

sum[j]=f[i]/f[i-1]*sum[j-1]+(g[i]-g[i-1])/f[i-1]

     y     =     k     *       x       +              b

于是可以发现使g[i]最大的点一定在一个上凸壳上,因为查询的斜率f[i]/f[i-1]不单调,用单调栈维护,二分查询即可。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define max(a,b) (a>b?a:b)
#define ll long long
const int maxn=2000010,inf=(int)1e9;
const double eps=1e-9;
using namespace std;
int n,m,sum[maxn],f[maxn],t[maxn],q[maxn],top;ll tim,g[maxn];char ch;
void read(int &x){
    for (ch=getchar();!isdigit(ch);ch=getchar());
    for (x=0;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
}
 
double slope(int i,int j){
    if (i==0||j==0) return inf;
    if (i==inf||j==inf) return -inf;
    return 1.0*(sum[i]-sum[j])/(double)(sum[i-1]-sum[j-1]);
}
 
void work(){
    q[1]=0,q[2]=1,top=2,q[top+1]=inf,g[1]=0;
    for (int i=2;i<=n;i++){
        for (;top&&slope(i,q[top])>slope(q[top],q[top-1])+eps;) {
            top--;
        }
        q[++top]=i,q[top+1]=inf;
    }
    for (int i=2;i<=m;i++){
        int l=1,r=top,mid=(l+r)>>1;double k=(1.0*f[i])/(1.0*f[i-1]);
        while (1){
            if (slope(q[mid],q[mid-1])+eps>=k&&slope(q[mid],q[mid+1])<=k+eps) break;
            else if (slope(q[mid],q[mid+1])>k+eps) l=mid+1;
            else r=mid-1;
            mid=(l+r)>>1;
        }
        g[i]=g[i-1]+(ll)sum[q[mid]]*f[i-1]-(ll)sum[q[mid]-1]*f[i];
    }
    printf("%lld\n",1ll*(g[m]+1ll*sum[n]*f[m]));
}
 
int main(){
    freopen("yume.in","r",stdin);freopen("yume.out","w",stdout);
    read(n),read(m);
    for (int i=1;i<=n;i++) read(t[i]),sum[i]=sum[i-1]+t[i];
    for (int i=1;i<=m;i++) read(f[i]);
    work();
    fclose(stdout);
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

省队集训 water

题目大意:有n个瓶子,都是m高,有些中间连了一些水管 (保证是一棵树),给出每个瓶子的底座高度h,以及水管,现在要在每个瓶子中灌水,然后会像连通器那样流起来,求有多少种每个瓶子水都是整数的静止方案数(...
  • abc473848880_
  • abc473848880_
  • 2015年07月11日 17:02
  • 280

[JZOJ5132][SDOI省队集训2017]子序列

题目大意字符集为9的字符串。 若干次询问区间本质不同的子序列个数。考虑暴力子序列要求本质不同。 假如每个位置向后每种字符的第一个位置连单向边。 设置一个虚点向区间每种字符第一个位置连单向边。 ...
  • WerKeyTom_FTD
  • WerKeyTom_FTD
  • 2017年06月03日 22:31
  • 276

SDOI2016第一轮省队集训

233
  • sxb_201
  • sxb_201
  • 2016年05月30日 21:23
  • 954

2015湖南省队集训DAY8——梦工厂

梦工厂 (yume.cpp/c/pas)Time Limit: 1 s Memory Limit: 128 M 问题描述「有时候用烂了的名字也会别有深意」 ——摘自EN 语录 “这里是...
  • Starry__Night
  • Starry__Night
  • 2015年07月11日 20:37
  • 591

省队集训DAY2

T1 题解 假设我们枚举数列{ai}中长度为len的区间,那么如何判断两个数列可以匹配呢? 对于提取的数列从小到大排序,{bi}从大到小排序,然后两两配对,如果所有的都满足>=h>=h,...
  • clover_hxy
  • clover_hxy
  • 2017年08月19日 20:34
  • 149

省队集训DAY5

T1 题解 因为是本质不同的字符串,所以考虑什么样的串会产生贡献。 对于一个字符串,我们使他出现的位置尽可能的考前,就是如果这个位置能从第i个串中匹配一定不会在第i+1个串中匹配。这样最...
  • clover_hxy
  • clover_hxy
  • 2017年08月19日 20:35
  • 157

省队集训DAY6

T1 题解 f[i]表示以字符i结尾的字符串的个数。 那么现在加入一个字符产生的贡献就是∑字符集大小i=0f[i]\sum_{i=0}^{字符集大小}f[i],然后把这个答案赋值给这...
  • clover_hxy
  • clover_hxy
  • 2017年08月19日 20:35
  • 146

省队集训DAY3

T1 题解 一共要使用六根木棍,那么分割的方法就两种{1,1,1,3},{1,1,2,2} 那么关键就是要计算2,3的数量。 cnt1[i]表示每种长度的木棍的方案数 cnt2[i]...
  • clover_hxy
  • clover_hxy
  • 2017年08月19日 20:34
  • 133

省队集训DAY4

T1 题解 将行与列分开考虑,每两个#之间属于一个连通块。 对于每个连通块建立节点,如果只从连通块中选取一个点,那么不会产生相互攻击的棋子。选取第2个点的时候会产生1的贡献,选取第三个点...
  • clover_hxy
  • clover_hxy
  • 2017年08月19日 20:35
  • 144

YZOJ 1572 [省队训练]calc

离线+分块思想挺神的题目啊。。。裸做肯定不行。因为询问可以变成前缀和加减,考虑将所有询问拆成两个点,按端点从左到右排序,一个一个做。暴力1:我们记mod[i][j]表示对i取模的值为j的数的个数的话,...
  • ziqian2000
  • ziqian2000
  • 2016年12月03日 00:38
  • 234
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:7.10省队集训梦工厂
举报原因:
原因补充:

(最多只允许输入30个字)