分类
标签
2-SAT AC自动机 BFS CDQ dfs DP fail树 FFT FFT&NTT FWT hash KD-Tree KMP LCA SPFA STL Tarjan Treap Trie 主席树 乱搞 二分 二分图匹配 二分答案 二维SPFA 交互 位运算 其他 最小生成树 分块 区间DP 半平面交 博弈论 可持久化 可持久化Trie树 后缀数组 图库 平衡树 并查集 插头DP 数学 数论 无旋Treap 日记 暴力 权值树状数组 栈 树DP 树套树 树状数组 树贪心 概率DP 模拟 欧拉定理 点分治 状压DP 生成函数 矩阵乘 线性规划 线段树 组合 网络流 群论 莫比乌斯反演 计算几何 贪心 费用流 高斯消元
754 字
4 分钟
[NOIP2011] 聪明的质监员
【问题描述】
小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有n个矿石,从 1 到n逐一编号,每个矿石都有自己的重量以及价值。检验矿产的流程是:
- 给定 m个区间;
- 选出一个参数W;
- 对于一个区间,计算矿石在这个区间上的检验值:
这批矿产的检验结果Y为各个区间的检验值之和。即:
若这批矿产的检验结果与所给标准值 S 相差太多,就需要再去检验另一批矿产。小 T 不想费时间去检验另一批矿产,所以他想通过调整参数 W 的值,让检验结果尽可能的靠近标准值 S,即使得S−Y的绝对值最小。请你帮忙求出这个最小值。
【输入】
输入文件 qc.in。 第一行包含三个整数n,m,S,分别表示矿石的个数、区间的个数和标准值。 接下来的n 行,每行2 个整数,中间用空格隔开,第i+1 行表示i 号矿石的重量wi 和价值vi 。 接下来的m 行,表示区间,每行2 个整数,中间用空格隔开,第i+n+1 行表示区间的两个端点 和。注意:不同区间可能重合或相互重叠。
【输出】
输出文件名为qc.out。 输出只有一行,包含一个整数,表示所求的最小值。
【输入输出样例】
qc.in
5 3 15
1 5
2 5
3 5
4 5
5 5
1 5
2 4
3 3
qc.out
10
【输入输出样例说明】
当W 选4 的时候,三个区间上检验值分别为20、5、0,这批矿产的检验结果为25,此时与标准值S 相差最小为10。
【数据范围】
对于10%的数据,有;
对于30%的数据,有;
对于50%的数据,有;
对于70%的数据,有;
对于100%的数据,有。
题解
三分W
求出Y 然后比较找最近的
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define LL long long
int n, m;
struct data
{
int w, v;
} a[200005];
struct Data
{
int l, r;
} Q[200005];
int Sumn[200005];
LL Sumv[200005];
LL check(int w)
{
Sumn[0] = 0;
Sumv[0] = 1;
for (int i = 1; i <= n; i++)
{
Sumn[i] = Sumn[i - 1] + (a[i].w > w);
Sumv[i] = Sumv[i - 1] + (a[i].w > w ? a[i].v : 0);
}
LL Y = 0;
for (int i = 1; i <= m; i++)
{
Y += (Sumn[Q[i].r] - Sumn[Q[i].l - 1]) * (Sumv[Q[i].r] - Sumv[Q[i].l - 1]);
}
return Y;
}
int main()
{
freopen("qc.in", "r", stdin);
freopen("qc.out", "w", stdout);
LL S;
scanf("%d%d%lld", &n, &m, &S);
int Max = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &a[i].w, &a[i].v);
Max = max(Max, a[i].w);
}
for (int i = 1; i <= m; i++)
{
scanf("%d%d", &Q[i].l, &Q[i].r);
}
LL l = 0, r = Max;
LL ans = 0x3fffffffffffffffLL;
while (l < r)
{
LL mid = l + r >> 1;
LL t = check(mid);
if (t < S)
{
ans = min(ans, abs(t - S));
r = mid;
}
else
{
ans = min(ans, abs(t - S));
l = mid + 1;
}
}
printf("%lld", ans);
//while (1);
}