_int_me @ 2018-10-13 11:26:18
没有想到正解 用了个线段树来计算Y 但是没有tle 只有1/2 wa 有没有dalao能指出这个程序里的缺陷..
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int n, m;
long long s, coo = 0;
int ff[200005][2], cc[800005], ll = 99999999, rr = 0;
long long co[800005];
int vv[2000005], ww[2000005];
void bd(int o, int l, int r, int qq)
{
if (l == r)
{
if (ww[l] >= qq)
{
cc[o] = 1;
co[o] = vv[l];
}
else
{
cc[o] = co[o] = 0;
}
return;
}
int mid = (l + r) >> 1;
bd(o << 1, l, mid, qq);
bd(o << 1 | 1, mid + 1, r, qq);
cc[o] = cc[o << 1] + cc[o << 1 | 1];
co[o] = co[o << 1] + co[o << 1 | 1];
}
long long ch(int o, int l, int r, int x, int y)
{
if (x <= l && y >= r)
{
coo += cc[o];
return co[o];
}
int mid = (l + r) >> 1;
int an = 0;
if (mid >= x)
{
an += ch(o << 1, l, mid, x, y);
}
if (mid + 1 <= y)
{
an += ch(o << 1 | 1, mid + 1, r, x, y);
}
return an;
}
int main()
{
scanf("%d%d%lld", &n, &m, &s);
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &ww[i], &vv[i]);
ll = min(ll, ww[i]);
rr = max(rr, ww[i]);
}
for (int i = 1; i <= m; i++)
{
scanf("%d%d", &ff[i][0], &ff[i][1]);
}
long long ss = 0;
while (ll <= rr)
{
int mid = (ll + rr) >> 1;
ss = 0;
bd(1, 1, n, mid);
for (int i = 1; i <= m; i++)
{
coo = 0;
ss += ch(1, 1, n, ff[i][0], ff[i][1]) * coo;
}
if (ss == s)
{
printf("0");
return 0;
}
if (ss - s > 0)
{
ll = mid + 1;
}
if (ss - s < 0)
{
rr = mid - 1;
}
}
long long sss = ss - s;
if (ss - s < 0)
{
sss = 0 - sss;
}
printf("%lld", sss);
return 0;
}
这里面的coo 是记录每次的符合条件的 矿石 的个数 ch函数返回的是 每次符合条件的矿石价值的和 ff数组记录区间 谢了
by Liquor✡鲸 @ 2018-10-13 11:31:35
大家都走准备初赛。。
只有你还在淡定的刷题
by 塔罗兰 @ 2018-10-13 11:36:44
不会,下一个
by Cesare @ 2018-10-14 15:18:20
正解前缀和优化二分不应该比这个好想吗。。。
by qrcqrc @ 2018-10-15 11:26:31
太巨了%%%%
by _int_me @ 2018-10-15 22:03:28
我..可能只想到二分吧 就把线段树扯上了