Blue Mary开公司
题目链接:luogu P4254
题目大意
要你支持两个操作。
加入一条线段,或者查询在某一个 x 坐标上哪一条线段对于的 y 值最大,输出这个最大的 y。
思路
这道题其实就是李超线段树板子题。
甚至还简单了?
注意你第一天是 b b b,第二天是 k + b k+b k+b,第 x x x 天使 ( x − 1 ) k + b (x-1)k+b (x−1)k+b。
代码
#include<cstdio>
#include<iostream>
using namespace std;
int q, x, n;
char s[101];
double k[1000001], b[1000001];
double f(int id, int x) {
return k[id] * (x - 1) + b[id];
}
struct XDTree {
int s[500001 << 2];
void up(int now, int l, int r, int x) {
if (l == r) {
if (f(x, l) > f(s[now], l)) {
s[now] = x;
}
return ;
}
int mid = (l + r) >> 1;
if (k[x] > k[s[now]]) {
if (f(x, mid) > f(s[now], mid)) up(now << 1, l, mid, s[now]), s[now] = x;
else up(now << 1 | 1, mid + 1, r, x);
}
else {
if (f(x, mid) > f(s[now], mid)) up(now << 1 | 1, mid + 1, r, s[now]), s[now] = x;
else up(now << 1, l, mid, x);
}
}
double query(int now, int l, int r, int x) {
if (l == r) return f(s[now], x);
int mid = (l + r) >> 1;
if (x <= mid) return max(f(s[now], x), query(now << 1, l, mid, x));
else return max(f(s[now], x), query(now << 1 | 1, mid + 1, r, x));
}
}T;
int main() {
scanf("%d", &q);
while (q--) {
scanf("%s", s + 1);
if (s[1] == 'Q') {
scanf("%d", &x);
printf("%d\n", (int)(T.query(1, 1, 50000, x) / 100));
}
else {
n++;
scanf("%lf %lf", &b[n], &k[n]);
T.up(1, 1, 50000, n);
}
}
return 0;
}