1. 程式人生 > 其它 >洛谷 4254 Blue Mary 開公司

洛谷 4254 Blue Mary 開公司

新增線性函式 $f(x)$,詢問 $x$ 取某個整數時最大的函式值; 李超樹模板

[JSOI2008] Blue Mary開公司

題面

題解

李超樹模板題

線段樹每個節點記錄一條直線。考慮新增一條直線,若該直線在區間內全面大於記錄的直線,則更新;全面小於,則棄去;否則遞迴兩個子節點。

如此一來,每個新增的線段都在其優勢位置得到了記錄。

單點詢問,取log層的最大值即可。

程式碼

//https://www.luogu.com.cn/problem/P4254
// nksbwen 20210727

#include <cstdio>
#include <algorithm>

using std::max;

const int MAXT=50011;

int N;

struct Func{
	double s, d;
} Zero, op;

double Cal(Func f, int t){
	return f.s+(t-1)*f.d;
}

bool Up(Func a, Func b, int c){
	return Cal(a, c)>Cal(b, c);
}

struct Node{
	int l, r;
	Func f;
} T[MAXT<<2];

void Build(int l, int r, int at=1){
	T[at].l=l;T[at].r=r;
	T[at].f=Zero;
	if(l==r)	return;
	int m=(l+r)>>1;
	Build(l, m, at<<1);
	Build(m+1, r, (at<<1)|1);
}

void Update(int at){
	bool l=Up(op, T[at].f, T[at].l), r=Up(op, T[at].f, T[at].r);
	if(l==r){
		if(l && r)	T[at].f=op;
		return;
	}
	Update(at<<1);Update((at<<1)|1);
}

int opt;

double Ask(int at){
	if(T[at].l==T[at].r)	return Cal(T[at].f, opt);
	int m=(T[at].l+T[at].r)>>1;
	double ret=Cal(T[at].f, opt);
	if(opt<=m)	return max(ret, Ask(at<<1));
	else	return max(ret, Ask((at<<1)|1));
}

int main(){
	
	scanf("%d", &N);
	
	int MaxT=50000;
	Build(1, MaxT);
	
	char cmd[111];
	for(int i=1;i<=N;++i){
		scanf("%s", cmd);
		if(cmd[0]=='P'){
			scanf("%lf%lf", &op.s, &op.d);
			Update(1);
		}
		else{
			scanf("%d", &opt);
			printf("%d\n", (int)(Ask(1)/100.0));
		}
	}
	
	return 0;
}