题目大意

小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有 n 个矿石,从 1
到 n 逐一编号,每个矿石都有自己的重量 wi 以及价值 vi。检验矿产的流程是:
1、给定 m 个区间[Li,Ri];
2、选出一个参数 W;
3、对于一个区间[Li,Ri],计算矿石在这个区间上的检验值 Yi :
这批矿产的检验结果 Y 为各个区间的检验值之和。即:
$$\sum_j 1\times \sum_j v_j,j\in[L_i,R_i]且w_j\geq W,j时矿石编号$$
若这批矿产的检验结果与所给标准值 S 相差太多,就需要再去检验另一批矿产。小 T
不想费时间去检验另一批矿产,所以他想通过调整参数 W 的值,让检验结果尽可能的靠近
标准值 S,即使得 S-Y 的绝对值最小。请你帮忙求出这个最小值。

解题关键

要把所有满足$w_j\geq W$的$\sum_j, \sum_j v_j$,一定要记得前缀和优化!这样就可以$O(n\log n)$解决,而不是$O(n^2\log n$了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std; #define UpdMax(x, y) x = max(x, y)
#define ll long long
const int MAX_N = 200010, MAX_Q = 200010;
const ll INF64 = 0x3f3f3f3f3f3f3f3fll;
ll W[MAX_N], V[MAX_N];
int L[MAX_N], R[MAX_N];
int N, TotQ;
ll Y, StdY; ll GetY(ll w)
{
static ll SumV[MAX_N];
static int SumCnt[MAX_N];
memset(SumV, 0, sizeof(SumV));
memset(SumCnt, 0, sizeof(SumCnt));
for (int i = 1; i <= N; i++)
{
SumV[i] = SumV[i - 1] + V[i] * (W[i] >= w);
SumCnt[i] = SumCnt[i - 1] + (W[i] >= w);
}
ll y = 0;
for (int q = 1; q <= TotQ; q++)
{
ll cnt = SumCnt[R[q]] - SumCnt[L[q] - 1], vSum = SumV[R[q]] - SumV[L[q] - 1];
y += cnt * vSum;
}
return Y = y;
} bool LeStdY(ll w)
{
return GetY(w) <= StdY;
} bool GeStdY(ll w)
{
return GetY(w) >= StdY;
} ll LowerBound(ll l, ll r, bool (*InUpperRange)(ll))
{
if (!InUpperRange(r))
return -1;
while (l < r)
{
ll mid = (l + r) / 2;
if (InUpperRange(mid))
r = mid;
else
l = mid + 1;
}
InUpperRange(l);
return l;
} ll UpperBoundSubtract1(ll l, ll r, bool (*InLowerRange)(ll))
{
if (!InLowerRange(l))
return -1;
while (l < r)
{
ll mid = (l + r + 1) / 2;
if (InLowerRange(mid))
l = mid;
else
r = mid - 1;
}
InLowerRange(l);
return l;
} int main()
{
scanf("%d%d%lld", &N, &TotQ, &StdY);
ll MaxW = 0;
for (int i = 1; i <= N; i++)
scanf("%lld%lld", W + i, V + i);
for (int i = 1; i <= N; i++)
UpdMax(MaxW, W[i]);
for (int i = 1; i <= TotQ; i++)
scanf("%d%d", L + i, R + i);
Y = INF64;
LowerBound(1, MaxW, LeStdY);
ll y1 = Y;
Y = INF64;
UpperBoundSubtract1(1, MaxW, GeStdY);
ll y2 = Y;
printf("%lld\n", min(abs(y1 - StdY), abs(y2 - StdY)));
return 0;
}

  

最新文章

  1. 【linux草鞋应用编程系列】_3_ 进程间通信
  2. poj 2515 差分序列,排列组合
  3. 20161106PM-接口
  4. SQL Server里的闩锁介绍
  5. 删除Android包
  6. vim如何进行分屏操作
  7. mapReduce编程之google pageRank
  8. 一个操作Sql2005数据库的类(备份,还原,分离,附加,添加删除用户等操作)(转载)
  9. js实现图片上传及预览----------------------&gt;&gt;兼容ie6-8 火狐以及谷歌
  10. 使用cvReleaseImage()释放图像出错
  11. Highways(求最小生成树的最大边)
  12. HDU 2414 Chessboard Dance (力模拟)
  13. 如何在MFC中启动其它的(.exe)可执行文件
  14. Codeforces Round #434 (Div. 2, based on Technocup 2018 Elimination Round 1)&amp;&amp;Codeforces 861A k-rounding【暴力】
  15. spark调用hdfsAPI
  16. 缓存--Redis
  17. 设计模式---状态变化模式之备忘录模式(Memento)
  18. Centos6.5安装ansible2.6.3
  19. 成都Uber优步司机奖励政策(4月16日)
  20. dubbo用户指南-总结

热门文章

  1. 怎样从SpringMVC返回json数据
  2. [Python3网络爬虫开发实战] 1.7.2-mitmproxy的安装
  3. 零基础入门学习Python(3)--小插曲之变量和字符串
  4. Leetcode 215.数组中的第k个最大元素
  5. 实现下载pdf文件
  6. Android二级缓存之物理存储介质上的缓存DiskLruCache
  7. 7-19 求链式线性表的倒数第K项(20 分)(单链表定义与尾插法)
  8. [K/3Cloud] 在插件中为辅助资料赋值
  9. OpenCV在Linux(Fedora)下搭建开发环境简述
  10. Toast自定义