首页 > 其他分享 >P1314 聪明的质监员(题解)

P1314 聪明的质监员(题解)

时间:2022-12-19 22:24:09浏览次数:37  
标签:int 题解 sum 质监 矿石 200500 long P1314 检验

题目

小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有 \(n\) 个矿石,从 \(1\) 到 \(n\) 逐一编号,每个矿石都有自己的重量 \(w_i\) 以及价值 \(v_i\) 。检验矿产的流程是:

1 、给定 \(m\) 个区间 \([l_i,r_i]\);

2 、选出一个参数 \(W\);

3 、对于一个区间 \([l_i,r_i]\),计算矿石在这个区间上的检验值 \(y_i\):

\[y_i=\sum\limits_{j=l_i}^{r_i}[w_j \ge W] \times \sum\limits_{j=l_i}^{r_i}[w_j \ge W]v_j \]

其中 \(j\) 为矿石编号。

这批矿产的检验结果 \(y\) 为各个区间的检验值之和。即:\(\sum\limits_{i=1}^m y_i\)

若这批矿产的检验结果与所给标准值 \(s\) 相差太多,就需要再去检验另一批矿产。小 T 不想费时间去检验另一批矿产,所以他想通过调整参数 \(W\) 的值,让检验结果尽可能的靠近标准值 \(s\),即使得 \(|s-y|\) 最小。请你帮忙求出这个最小值。

解析

这是一道比较清晰明了的二分答案。

可以看出整个式子的自变量是 \(W\),因变量是此时得到的 \(y\)。

那么就来判断是否可以运用二分来解,首先判断单调性:

当 \(W\) 比最轻的矿石质量还小时,所有的矿石都可以参与运算,计算出来的 \(y\) 必定最大。

当 \(W\) 比最重的矿石质量还大时,所有的矿石都不能参与运算,计算出来的 \(y\) 必定最小。

因此,\(W\) 越小,参与计算的数就越多,\(y\) 也就越大。

所以单调性出来了,我们就可以在区间内通过枚举 \(W\) 来得到答案了。

然后就 \(TLE\) 了……

优化

查看代码发现,二分部分肯定是不会有什么超时的地方,那就是 check 函数的问题了。

发现在每次计算过程中由于重复计算造成了大量的浪费,于是考虑用前缀和优化。

使用 sum_n[i] 来表示区间中合格部分数量,sum_v[i] 来记录区间中合格部分价值。

最后进行计算。

#include<iostream>
#include<algorithm>
#include<cstdio>
#define int long long

using namespace std;

int n,m,s;
int w[200500],v[200500];
int l[200500],r[200500];

int sum_n[200500],sum_v[200500];

long long ans = 0;

void init()
{
    scanf("%lld%lld%lld",&n,&m,&s);
    for(int i = 1;i <= n; i++)
        scanf("%lld%lld",&w[i],&v[i]);
    for(int i = 1;i <= m; i++)
        scanf("%lld%lld",&l[i],&r[i]);
    
    return ;
}

long long check(int W)
{
    long long ans = 0;
    for(int i = 1;i <= n; i++)
    {
        if( W > w[i] )// 要用前缀和,不然会炸掉!!!
        {
            sum_n[i] = sum_n[i-1];
            sum_v[i] = sum_v[i-1]; 
        }
        else
        {
            sum_n[i] = sum_n[i-1] + 1;
            sum_v[i] = sum_v[i-1] + v[i]; 
        }
    }

    for(int i = 1;i <= m; i++)
    {
        long long a,b;
        a = sum_v[r[i]] - sum_v[l[i]-1];
        b = sum_n[r[i]] - sum_n[l[i]-1];
        ans += a*b;
    }

    return ans;
}

long long _abs(long long a)
{
    if( a > 0 )
        return a;
    return -a;
}

signed main()
{
    init();

    int left = 0,right = 1000000,mid;

    while( left <= right )
    {
        mid  = (left + right)>>1;
        if( check(mid) > s )
            left = mid + 1;
        else    
            right = mid - 1;
    }
    ans = _abs(check(left) - s);
    
    if( _abs(check(right) - s) < ans )
        ans = _abs(check(right) - s);
    
    printf("%lld",ans);
    return 0;
}

总结

题总体来说并不算难,但细节仍需要注意。

例如在考试中,就很有可能会忘记前缀和优化的问题,导致失去 30 分。

还有一直存在的 long long 的问题,同样会影响数十分。

要注重时间复杂度,重视算法的优化。做题时一定要每道题计算时间复杂度,不然考场追悔莫及。

标签:int,题解,sum,质监,矿石,200500,long,P1314,检验
From: https://www.cnblogs.com/JXYBJ/p/congmingdezhijianyuan.html

相关文章

  • NOIP2022题解
    \(\mathbf{NOIP2022}\)\(\mathbf{plant}\)\(\mathbf{Describe}\)题面\(\mathbf{Solution}\)我们记\(f(x,y)\)表示从\((x,y)\)向右连续的\(0\)段的长度,\(up_......
  • NOIP2022 游记 & 简要题解
    游.寄\(\text{Day0}\)由于疫情的原因,原本预定的团建活动鸽了,于是就在机房里放送起来,打了一天的三国杀,身份、国战都打了。中午教练请吃饭,吃到了来一中之后最好的一餐。......
  • 剑指offer 题解目录(C++)
    序号题目知识点难度1​​二维数组中的查找​数组查找较难2​​替换空格​字符串较难3​​从尾到头打印链表​链表较难4​​重建二叉树​树中等5​​用两个栈实现队列......
  • mysql及redis环境部署时遇到的问题解决
    redis开启远程访问redis默认只允许本地访问,要使redis可以远程访问可以修改redis.conf打开redis.conf文件在NETWORK部分有说明解决办法:注释掉bind127.0.0.1可以使所有的ip访......
  • Element UI Table 固定列遮挡横向滚动条问题解决方案记录
    .el-table{::v-deep.el-table__fixed{height:auto!important;bottom:16px;//横向滚动条高度}::v-deep.el-table__fixed::before{display......
  • 问题解决系列:NameError: name 'platform_system' is not defined
    问题场景使用 ​​pip​​​安装依赖的时候,更新之后,更新的依赖不能用。比如我将机器的​​ansible​​​版本指定安装​​2.7.11​​​版本,安装成功之后,使用命令​​ansible......
  • JAG Spring Contest 2012 G PLAY in BASIC 题解
    提交链接其实就是个大模拟。首先对输入的串进行处理,把所有的命令分开,并把连续的停顿合并。为了方便,定义一个时间单位为全音符的\(\frac1{128}\),这样所有命令的持续时间都......
  • JAG Spring Contest 2012 G PLAY in BASIC 题解
    提交链接其实就是个大模拟。首先对输入的串进行处理,把所有的命令分开,并把连续的停顿合并。为了方便,定义一个时间单位为全音符的\(\frac1{128}\),这样所有命令的持续时间都......
  • 洛谷 P6580 [Ynoi 2019] 美好的每一天~ 不连续的存在 题解
    既然是YNOI那肯定是要分块的。先考虑树是一条链的情况,可以直接回滚莫队,对n个节点组成的序列分块。在回滚莫队的过程中,当前维护的区间一共会扩展\(O(n\sqrtn)\)次,每次都是......
  • Android Studio使用Mob实现短信验证功能遇到的问题解决
    一、Mob短信验证​​全球领先的数据智能科技平台-MobTech袤博解决​​进行注册登入 登入成功后,点击开发者服务中的短信验证,进入开发者平台填好信息创建成功后显示下图,可以......